26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
135 for(
int x = 0; x < 4; x++)
144 for(
int x = 0; x < 4; x++)
153 for(
int x = 0; x < 4; x++)
158 for(
int x = 0; x < 4; x++)
162 for(
int x = 0; x < 3; x++)
199 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete FrontCodePtr");
262 for(
int x = 0; x < 4; x++)
266 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
271 for(
int x = 0; x < 4; x++)
275 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
304 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
370 bool TempDerail =
false;
416 else if((NextElementPosition > -1) && (NextEntryPos > -1))
487 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
497 for(
int x = 0; x < 4; x++)
504 for(
int x = 0; x < 4; x++)
765 int LockedVectorNumber;
894 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
895 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
896 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
897 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
898 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
899 "of a shortage of on train crew"};
906 if(DwellTime < TDateTime(30.0 / 86400))
908 DwellTime = TDateTime(30.0 / 86400);
910 int randval = random(10000);
915 if(randval < Utilities->MinorDelayCutoff)
922 if(randval < Utilities->ModerateDelayCutoff)
929 if(randval < Utilities->MajorDelayCutoff)
944 if(
NewDelay <
double(DwellTime) * 1440)
950 NewDelay -= double(DwellTime) * 1440;
1011 int randval2 = rand() % 24;
1012 AnsiString Reason = ReasonArray[randval2];
1015 " minutes because " + Reason);
1017 " minutes because " + Reason);
1023 " minutes because of a minor problem");
1025 " minutes because of a minor problem");
1175 if(BufferLocation ==
"")
1180 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1242 int NextElementPosition, NextEntryPos;
1266 NextElementPosition = -1;
1269 if((NextElementPosition > -1) && (NextEntryPos > -1))
1391 AnsiString StationName;
1402 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1415 if((NextElementPosition > -1) && (NextEntryPos > -1))
1549 if(TIFEntryPos == 0)
1586 if(NextElementPosition > -1)
1623 AnsiString Loc =
"";
1624 bool LocNamed =
false;
1653 Loc =
"outside railway";
1685 NextElementPosition = -1;
1696 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1714 if((NextElementPosition > -1) && (NextEntryPos > -1))
1752 FirstPair.second).
GetELink() == TempELink))
1757 SecondPair.second).
GetELink() == TempELink))
1771 FirstPair.second).
GetELink() == TempELink))
1776 SecondPair.second).
GetELink() == TempELink))
1790 FirstPair.second).
GetELink() == TempELink))
1795 SecondPair.second).
GetELink() == TempELink))
1825 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1828 int NewLastElement = 0, NewLastExitPos = 0;
1846 if(NewLastElement == -1)
1852 if(NewLastExitPos == -1)
1856 LastElement = NewLastElement;
1857 LastExitPos = NewLastExitPos;
1860 if(CumDistance < 1200)
1866 int FirstDistance = 0;
1867 if(CumDistance >= 1200)
1869 FirstDistance = 100;
1873 FirstDistance = 1200 - CumDistance;
1875 if(FirstDistance < 100)
1877 FirstDistance = 100;
1903 if(VectorIT->RouteNumber == RouteNumber)
1940 " failed when changing aspect.\nTrains can only pass under signaller control.");
1974 LockedVectorNumber)))
2133 for(
int x = 0; x < 4; x++)
2140 for(
int x = 0; x < 4; x++)
2166 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2171 if(OtherTrainEntryPos == -1)
2173 throw Exception(
"Error - OtherTrainEntryPos not set");
2192 int OtherTrainID = -1;
2193 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2284 bool StopRequired =
false;
2297 int NextElementEntryPos = -1;
2298 int NextElementExitPos = -1;
2299 bool TrainOnNextElement =
false;
2300 bool StopSignalAtNextElement =
false;
2301 if(ForwardConnection)
2309 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2311 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2367 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2580 if(Code.Length() != 4)
2584 for(
int x = 1; x < 5; x++)
2591 for(
int x = 0; x < 4; x++)
2754 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2767 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2782 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2791 TRect SourceRect, DestRect;
2793 DestRect.init(0, 0, 8, 8);
2796 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2798 TempGraphic->PixelFormat = pf8bit;
2799 TempGraphic->Width = 16;
2800 TempGraphic->Height = 16;
2806 TempGraphic->Transparent =
true;
2810 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2811 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2817 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2825 else if(TempElement.
SpeedTag == 89)
2829 else if(TempElement.
SpeedTag == 90)
2833 else if(TempElement.
SpeedTag == 91)
2837 else if(TempElement.
SpeedTag == 92)
2841 else if(TempElement.
SpeedTag == 93)
2845 else if(TempElement.
SpeedTag == 94)
2849 else if(TempElement.
SpeedTag == 95)
2853 TempGraphic->Transparent =
true;
2857 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2858 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2867 for(
int x = 0; x < 40; x++)
2882 TempGraphic->Transparent =
true;
2886 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2887 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2889 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2903 TempGraphic->Transparent =
true;
2907 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2908 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2912 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2915 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2920 TempGraphic->Transparent =
true;
2924 int BDVectorPos = -1;
2933 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2938 TempGraphic->Transparent =
true;
2942 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2943 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2945 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2951 TempGraphic->Transparent =
true;
2955 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2956 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3224 throw Exception(
"Error, same train on two different bridge tracks");
3270 AnsiString(EntryPos) +
"," +
HeadCode);
3287 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3306 AnsiString(EntryPos) +
"," +
HeadCode);
3315 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3348 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3349 int LockedVectorNumber;
3362 TRect SourceRect, DestRect;
3363 DestRect.init(0, 0, 8, 8);
3370 int FirstELink, SecondELink = -1;
3373 if(RoutePair2.first > -1)
3382 if(SecondELink == -1)
3384 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3389 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3399 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3400 DestGraphic->PixelFormat = pf8bit;
3401 DestGraphic->Width = 8;
3402 DestGraphic->Height = 8;
3403 DestGraphic->Transparent =
true;
3406 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3415 PrefDirElement, LockedVectorNumber))
3430 if(ElementEntryPos > 1)
3452 AnsiString(EntryPos) +
"," +
HeadCode);
3454 bool WrongRoute =
false;
3480 int LinkNumber = TrackElement.
Link[EntryPos];
3481 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3486 bool LogActionErrorCalled =
false;
3496 LogActionErrorCalled =
true;
3513 else if(LinkNumber == 3)
3521 LogActionErrorCalled =
true;
3538 else if(LinkNumber == 7)
3546 LogActionErrorCalled =
true;
3563 else if(LinkNumber == 9)
3571 LogActionErrorCalled =
true;
3603 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3608 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3618 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3623 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3632 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3653 bool ColourError =
false, ColourError2 =
false;
3658 ColourError2 =
true;
3660 for(
int x = 0; x < 4; x++)
3665 ColourError2 =
true;
3671 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3675 for(
int x = 0; x < 4; x++)
3762 AnsiString(EntryPos) +
"," +
HeadCode);
3763 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3764 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3765 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3766 TrainInFrontInSignallerModeFlag =
false;
3767 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3768 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3769 bool SignallerStopRequired =
false;
3780 if(CurrentTrackVectorPosition > -1)
3784 if((EntryPos == 0) || (EntryPos == 2))
3797 else if(EntryPos == 1)
3821 EntryHalfLength = CurrentElementHalfLength;
3826 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3830 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3877 FrontElementMaxSpeed = LimitingSpeed;
3913 double ExitSpeedAtMaxBraking;
3918 ExitSpeedAtMaxBraking = 0;
3928 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3930 SpeedToUse = ExitSpeedAtMaxBraking;
3934 SpeedToUse = LimitingSpeed;
3949 RedSignalFlag =
false;
3950 BuffersFlag =
false;
3951 StationFlag =
false;
3952 BuffersOrContinuationNowFlag =
false;
3953 ContinuationNextFlag =
false;
3956 CumulativeLength += (2 * CurrentElementHalfLength);
3959 SignallerStopRequired =
true;
3981 bool StopRequired =
false;
3995 StationFlag =
false;
4001 BuffersOrContinuationNowFlag =
true;
4003 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4007 if((EntryPos == 0) || (EntryPos == 2))
4029 if(NextTrackVectorPosition > -1)
4034 if((NextEntryPos == 0) || (NextEntryPos == 2))
4047 else if(NextEntryPos == 1)
4060 if(NextEntryPos > 1)
4074 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4086 RedSignalFlag =
true;
4108 TrainInFrontInSignallerModeFlag =
true;
4132 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4144 double MaxHalfSpeed;
4148 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4150 MaxHalfSpeed = FrontElementMaxSpeed;
4154 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4162 bool HalfSpeedLimited =
false;
4166 HalfSpeedLimited =
true;
4196 if(HalfSpeedLimited)
4221 if(SignallerStopRequired)
4237 int TempMaxExitSpeed;
4240 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4242 MaxExitSpeedAtHalfBraking = 0;
4246 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4250 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4252 TempMaxExitSpeed = FrontElementMaxSpeed;
4256 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4268 if(ExitSpeedHalfSquared < 10)
4278 if(ExitSpeedFullSquared < 10)
4350 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4351 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4375 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4376 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4386 if(!BuffersOrContinuationNowFlag)
4388 if(NextSpeedLimit < LimitingSpeed)
4390 LimitingSpeed = NextSpeedLimit;
4394 int TempMaxExitSpeed;
4398 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4400 MaxExitSpeedAtHalfBraking = 0;
4404 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4406 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4408 TempMaxExitSpeed = FrontElementMaxSpeed;
4412 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4423 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4436 if(!BuffersOrContinuationNowFlag)
4438 CurrentTrackVectorPosition = NextTrackVectorPosition;
4439 EntryPos = NextEntryPos;
4440 CurrentElementHalfLength = NextElementHalfLength;
4443 ContinuationNextFlag =
true;
4447 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4467 if(ExitSpeedHalfSquared < 10)
4477 if(ExitSpeedFullSquared < 10)
4540 double DeltaExitTimeToMaxInSecs;
4541 double DistanceToMax;
4550 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4552 DistanceToMax = EntryHalfLength;
4555 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4556 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4573 double DeltaExitTimeToMaxInSecs;
4574 double DistanceToMax;
4583 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4585 DistanceToMax = EntryHalfLength / 2;
4588 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4589 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4600 if(ExitSpeedHalfSquared < 10)
4610 if(ExitSpeedFullSquared < 10)
4629 if((EntryPos == 0) || (EntryPos == 2))
4651 if(NextTrackVectorPosition > -1)
4653 int NextElementLength;
4654 if(NextEntryPos > 1)
4662 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4849 int ElementCount = 0;
4857 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4875 CurrentTrackVectorPosition).
Attribute != 4))
4915 if((EntryPos == 0) || (EntryPos == 2))
4937 CurrentTrackVectorPosition = NextTrackVectorPosition;
4938 EntryPos = NextEntryPos;
4940 if(ElementCount > 1000)
4968 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4993 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4994 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4995 int RouteStartPosition;
4997 int PlatformPosition;
4999 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5015 if(Distance > (4000 + LeadElementDistance))
5038 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5041 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5087 if(!PlatformFoundFlag)
5089 PlatformPosition = CurrentTrackVectorPosition;
5092 PlatformFoundFlag =
true;
5108 if((EntryPos == 0) || (EntryPos == 2))
5152 if(ElementNumber < 2)
5154 SkipRouteCheck =
true;
5158 SkipRouteCheck =
false;
5160 if(ElementNumber == 1)
5162 RouteStartPosition = CurrentTrackVectorPosition;
5172 if(ElementNumber > 1)
5176 RouteOrPartRouteSet =
true;
5180 RouteOrPartRouteSet =
false;
5183 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5190 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5191 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5203 Distance += CurrentTrackElement.
Length01;
5207 Distance += CurrentTrackElement.
Length23;
5209 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5210 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5211 CurrentTrackVectorPosition = NextTrackVectorPosition;
5212 EntryPos = NextEntryPos;
5249 return(RepeatHeadCode);
5271 bool FrontValid =
false, RearValid =
false;
5272 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5276 TrainToBeJoinedBy = NULL;
5290 int TrainToBeJoinedByID = -1;
5311 if((TrainToBeJoinedByID < 0) && RearValid)
5330 if(TrainToBeJoinedByID < 0)
5332 TrainToBeJoinedBy = NULL;
5337 if(!TrainToBeJoinedBy->
Stopped())
5339 TrainToBeJoinedBy = NULL;
5349 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5350 TDateTime TimetableNonRepeatTime,
bool Warning)
5386 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5387 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5388 int IntMinsLate = 0;
5393 ActionLog =
" arrived at ";
5402 ActionLog =
" terminated at ";
5407 ActionLog =
" departed from ";
5409 if(ActionType ==
Pass)
5411 ActionLog =
" passed ";
5415 ActionLog =
" created at ";
5417 if(ActionType ==
Enter)
5419 ActionLog =
" entered railway at ";
5425 if(ActionType ==
Leave)
5427 ActionLog =
" left railway at ";
5431 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5435 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5439 ActionLog =
" joined by ";
5443 ActionLog =
" changed direction at ";
5447 ActionLog =
" became new service ";
5451 ActionLog =
" taken under signaller control at ";
5455 ActionLog =
" restored to timetable control at ";
5461 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5465 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5469 ActionLog =
" REMOVED FROM RAILWAY at ";
5474 ActionLog =
" received signaller authority to proceed";
5478 ActionLog =
" received signaller authority to step forward";
5482 ActionLog =
" changed direction under signaller control at ";
5486 ActionLog =
" received signaller authority to pass stop signal";
5490 ActionLog =
" received signaller instruction to stop";
5494 ActionLog =
" stopped on signaller instruction ";
5498 ActionLog =
" joined under signaller control by ";
5502 ActionLog =
" suffered an onboard power failure at ";
5506 ActionLog =
" failure repaired at ";
5510 ActionLog =
" left railway under signaller control at ";
5512 if(OtherHeadCode !=
"")
5514 OtherHeadCode +=
" at ";
5527 bool TimePerformance =
true;
5535 TimePerformance =
false;
5539 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5541 if(ActionType ==
Pass)
5555 IntMinsLate = int(ceil(MinsLate));
5559 IntMinsLate = int(floor(MinsLate));
5561 if(IntMinsLate == 0)
5563 PerfLog =
" on time";
5565 else if(IntMinsLate == 1)
5567 PerfLog =
" 1 minute late";
5569 else if(IntMinsLate == -1)
5571 PerfLog =
" 1 minute early";
5573 else if(IntMinsLate > 1)
5575 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5577 else if(IntMinsLate < -1)
5579 int PosIntMinsLate = -IntMinsLate;
5580 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5582 if(LocationName.Pos(
'-') > 0)
5584 PerfLog =
"," + PerfLog;
5598 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5602 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5607 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5613 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5617 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5622 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5628 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5632 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5637 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5643 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5647 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5666 AnsiString LocName =
"";
5733 if(LocationName ==
"")
5737 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5738 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5739 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5743 if(LocationName !=
"")
5751 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5756 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5770 int LeadPosA = FirstNamedElementPos;
5771 int LeadPosB = FirstNamedLinkedElementPos;
5772 int LeadPosC = SecondNamedElementPos;
5773 int LeadPosD = SecondNamedLinkedElementPos;
5775 int LeadNumAtLoc = 0;
5792 if(LeadNumAtLoc < 4)
5796 SecondNamedLinkedElementPos))
5798 FirstNamedElementPos = LeadPosA;
5799 FirstNamedLinkedElementPos = LeadPosB;
5800 SecondNamedElementPos = LeadPosC;
5801 SecondNamedLinkedElementPos = LeadPosD;
5805 int MidNumAtLoc = 0;
5822 if(LeadNumAtLoc > MidNumAtLoc)
5825 FirstNamedElementPos = LeadPosA;
5826 FirstNamedLinkedElementPos = LeadPosB;
5827 SecondNamedElementPos = LeadPosC;
5828 SecondNamedLinkedElementPos = LeadPosD;
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5852 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5853 FrontTrainRearPosition = FirstNamedElementPos;
5854 RearTrainFrontPosition = SecondNamedElementPos;
5855 RearTrainRearPosition = SecondNamedLinkedElementPos;
5859 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5860 FrontTrainRearPosition = SecondNamedElementPos;
5861 RearTrainFrontPosition = FirstNamedElementPos;
5862 RearTrainRearPosition = FirstNamedLinkedElementPos;
5869 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5870 FrontTrainRearPosition = SecondNamedElementPos;
5871 RearTrainFrontPosition = FirstNamedElementPos;
5872 RearTrainRearPosition = FirstNamedLinkedElementPos;
5876 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5877 FrontTrainRearPosition = FirstNamedElementPos;
5878 RearTrainFrontPosition = SecondNamedElementPos;
5879 RearTrainRearPosition = SecondNamedLinkedElementPos;
5882 RearTrainExitPos = -1;
5883 for(
int x = 0; x < 4; x++)
5887 RearTrainExitPos = x;
5891 if(RearTrainExitPos == -1)
5893 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5895 FrontTrainExitPos = -1;
5896 for(
int x = 0; x < 4; x++)
5900 FrontTrainExitPos = x;
5904 if(FrontTrainExitPos == -1)
5906 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5909 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5916 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5936 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5944 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5945 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5946 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5985 double NewTrainPowerAtRail;
5991 NewTrainMass =
Mass * double(MassPercent)/100.0;
5993 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5994 if(NewTrainPowerAtRail == 0)
5996 NewTrainPowerAtRail = 0.08;
6004 NewTrainMass =
Mass;
6078 if(LocationName ==
"")
6082 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
6083 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
6084 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
6088 if(LocationName !=
"")
6095 SecondNamedLinkedElementPos))
6099 SecondNamedLinkedElementPos))
6113 int LeadPosA = FirstNamedElementPos;
6114 int LeadPosB = FirstNamedLinkedElementPos;
6115 int LeadPosC = SecondNamedElementPos;
6116 int LeadPosD = SecondNamedLinkedElementPos;
6118 int LeadNumAtLoc = 0;
6135 if(LeadNumAtLoc < 4)
6139 SecondNamedLinkedElementPos))
6141 FirstNamedElementPos = LeadPosA;
6142 FirstNamedLinkedElementPos = LeadPosB;
6143 SecondNamedElementPos = LeadPosC;
6144 SecondNamedLinkedElementPos = LeadPosD;
6148 int MidNumAtLoc = 0;
6165 if(LeadNumAtLoc > MidNumAtLoc)
6168 FirstNamedElementPos = LeadPosA;
6169 FirstNamedLinkedElementPos = LeadPosB;
6170 SecondNamedElementPos = LeadPosC;
6171 SecondNamedLinkedElementPos = LeadPosD;
6185 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6195 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6196 FrontTrainRearPosition = FirstNamedElementPos;
6197 RearTrainFrontPosition = SecondNamedElementPos;
6198 RearTrainRearPosition = SecondNamedLinkedElementPos;
6202 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6203 FrontTrainRearPosition = SecondNamedElementPos;
6204 RearTrainFrontPosition = FirstNamedElementPos;
6205 RearTrainRearPosition = FirstNamedLinkedElementPos;
6212 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6213 FrontTrainRearPosition = SecondNamedElementPos;
6214 RearTrainFrontPosition = FirstNamedElementPos;
6215 RearTrainRearPosition = FirstNamedLinkedElementPos;
6219 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6220 FrontTrainRearPosition = FirstNamedElementPos;
6221 RearTrainFrontPosition = SecondNamedElementPos;
6222 RearTrainRearPosition = SecondNamedLinkedElementPos;
6225 RearTrainExitPos = -1;
6226 for(
int x = 0; x < 4; x++)
6230 RearTrainExitPos = x;
6234 if(RearTrainExitPos == -1)
6236 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6238 FrontTrainExitPos = -1;
6239 for(
int x = 0; x < 4; x++)
6243 FrontTrainExitPos = x;
6247 if(FrontTrainExitPos == -1)
6249 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6252 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6259 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6279 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6287 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6288 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6289 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6327 double NewTrainPowerAtRail;
6333 NewTrainMass =
Mass * double(MassPercent)/100.0;
6335 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6336 if(NewTrainPowerAtRail == 0)
6338 NewTrainPowerAtRail = 0.08;
6346 NewTrainMass =
Mass;
6465 TTrain *TrainToBeJoinedBy;
6498 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6500 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6561 int RouteNumber = -1;
6566 int CorrectRouteID = OR.
RouteID;
6571 bool FirstPass =
true;
6576 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6690 for(
int x = 0; x < IncNum; x++)
6723 else if(Ptr->
Command ==
"jbo")
6728 else if(Ptr->
Command ==
"dsc")
6739 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6745 bool IncludeFER =
false;
6753 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6758 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6769 else if(Ptr->
Command ==
"Fjo")
6775 else if(Ptr->
Command ==
"Frh")
6785 else if(Ptr->
Command ==
"Frh-sh")
6836 else if(Ptr->
Command ==
"jbo")
6841 else if(Ptr->
Command ==
"dsc")
6846 else if(Ptr->
Command ==
"cdt")
6854 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7251 int RouteNumber = -1;
7256 int CorrectRouteID = OR.
RouteID;
7261 bool FirstPass =
true;
7266 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7294 ",FloatingLabelNextString" +
"," +
HeadCode);
7295 AnsiString RetStr =
"", LocationName =
"";
7298 if(ActionTime == TDateTime(-1))
7302 if(ActionTime == TDateTime(-1))
7308 if(ActionTime != TDateTime(-1))
7316 throw Exception(
"Error - start entry in FloatingLabelNextString");
7360 else if(Ptr->
Command ==
"Fns")
7366 else if(Ptr->
Command ==
"F-nshs")
7397 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7399 else if(Ptr->
Command ==
"Frh")
7401 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7403 else if(Ptr->
Command ==
"Fer")
7405 AnsiString AllowedExits =
"";
7408 else if(Ptr->
Command ==
"Fjo")
7413 else if(Ptr->
Command ==
"jbo")
7418 else if(Ptr->
Command ==
"fsp")
7423 else if(Ptr->
Command ==
"rsp")
7428 else if(Ptr->
Command ==
"cdt")
7432 else if(Ptr->
Command ==
"dsc")
7441 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7485 else if(Ptr->
Command ==
"Fns")
7491 else if(Ptr->
Command ==
"F-nshs")
7522 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7524 else if(Ptr->
Command ==
"Frh")
7526 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7528 else if(Ptr->
Command ==
"Fer")
7530 AnsiString AllowedExits =
"";
7533 else if(Ptr->
Command ==
"Fjo")
7538 else if(Ptr->
Command ==
"jbo")
7543 else if(Ptr->
Command ==
"fsp")
7548 else if(Ptr->
Command ==
"rsp")
7553 else if(Ptr->
Command ==
"cdt")
7557 else if(Ptr->
Command ==
"dsc")
7566 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7610 else if(Ptr->
Command ==
"Fns")
7616 else if(Ptr->
Command ==
"F-nshs")
7647 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7649 else if(Ptr->
Command ==
"Frh")
7651 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7653 else if(Ptr->
Command ==
"Fer")
7655 AnsiString AllowedExits =
"";
7658 else if(Ptr->
Command ==
"Fjo")
7663 else if(Ptr->
Command ==
"jbo")
7668 else if(Ptr->
Command ==
"fsp")
7673 else if(Ptr->
Command ==
"rsp")
7678 else if(Ptr->
Command ==
"cdt")
7682 else if(Ptr->
Command ==
"dsc")
7826 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7827 AnsiString DepTime =
"", EventTime =
"";
7828 bool CDTFlag =
false;
7830 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7831 AnsiString TowardsLocation =
"";
7834 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7836 TowardsLocation = AVI->LocationName;
7838 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7847 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7854 if(AVI->Command ==
"cdt")
7859 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7874 RetStr +=
"\nNew service splits at approx. " + EventTime;
7878 if(AVI->Command ==
"jbo")
7893 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7897 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7912 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7916 if(AVI->Command ==
"Fjo")
7931 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7935 if(AVI->Command ==
"Frh")
7937 RetStr +=
"\nNew service finishes and remains at the location.";
7941 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7948 if(TowardsLocation !=
"")
7950 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7954 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7959 if(TowardsLocation !=
"")
7961 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7965 RetStr +=
"\nNew service departs at " + DepTime;
7974 if(TowardsLocation !=
"")
7976 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
7980 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
7985 if(TowardsLocation !=
"")
7987 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
7991 RetStr +=
"\nNew service departs at approx. " + DepTime;
8008 if(TowardsLocation !=
"")
8010 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8014 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8019 if(TowardsLocation !=
"")
8021 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8025 RetStr +=
"\nNew service departs at approx. " + DepTime;
8044 ",FloatingTimetableString" +
"," +
HeadCode);
8045 AnsiString RetStr =
"", PartStr =
"";
8047 bool SkipDep =
false, SkipDepActedOn =
false;
8053 throw Exception(
"Error - start entry in FloatingTimetableString");
8056 bool FirstPass =
true;
8069 AnsiString TrainLoc =
"";
8115 AnsiString TrainLoc =
"";
8155 else if(Ptr->
Command ==
"Fns")
8161 else if(Ptr->
Command ==
"F-nshs")
8194 else if(Ptr->
Command ==
"Frh")
8198 else if(Ptr->
Command ==
"Fer")
8200 AnsiString AllowedExits =
"";
8203 else if(Ptr->
Command ==
"Fjo")
8208 else if(Ptr->
Command ==
"jbo")
8213 else if(Ptr->
Command ==
"fsp")
8223 PartStr+=
", split mass%-Power% = 50-50";
8226 else if(Ptr->
Command ==
"rsp")
8236 PartStr+=
", split mass%-Power% = 50-50";
8239 else if(Ptr->
Command ==
"cdt")
8243 else if(Ptr->
Command ==
"dsc")
8249 RetStr = RetStr +
'\n' + PartStr;
8263 SkipDepActedOn =
true;
8274 RetStr =
"Timetable finished";
8278 RetStr =
"No timetable";
8282 return(
"Timetable:\n" + RetStr);
8435 bool ForwardHeadCode;
8439 ForwardHeadCode =
true;
8444 ForwardHeadCode =
false;
8587 if(ColourNumber == 0)
8591 else if(ColourNumber == 1)
8595 else if(ColourNumber == 2)
8599 else if(ColourNumber == 3)
8603 else if(ColourNumber == 4)
8607 else if(ColourNumber == 5)
8611 else if(ColourNumber == 6)
8615 else if(ColourNumber == 7)
8619 else if(ColourNumber == 8)
8623 else if(ColourNumber == 9)
8627 else if(ColourNumber == 10)
8631 else if(ColourNumber == 11)
8635 else if(ColourNumber == 12)
8639 else if(ColourNumber == 13)
8643 else if(ColourNumber == 14)
8655 for(
int x = 0; x < 4; x++)
8662 for(
int x = 0; x < 4; x++)
8747 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8750 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8751 bool GiveMessagesFalse =
false;
8752 bool CheckLocationsExistInRailwayTrue =
true;
8759 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8762 if(Marker[6] ==
'1')
9227 bool HideFlashingTrain =
true;
9230 Graphics::TBitmap *SmallTrainBitmap;
9271 HideFlashingTrain =
false;
9276 HideFlashingTrain =
false;
9281 HideFlashingTrain =
false;
9286 HideFlashingTrain =
false;
9291 HideFlashingTrain =
false;
9295 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9299 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9323 for(
int y = 0; y < 3; y++)
9327 bool FoundFlag =
false;
9338 if(IMPair.first != IMPair.second)
9365 if((LocationName ==
"") && (
MidElement > -1))
9369 if((LocationName ==
"") && (
LagElement > -1))
9373 if(LocationName ==
"")
9375 throw Exception(
"Error - Location name not set in TrainAtLocation");
9386 for(
int x = 0; x < 4; x++)
9398 for(
int x = 0; x < 4; x++)
9415 AnsiString(LinkNumber) +
"," +
HeadCode);
9467 int DistanceToRedSignal = 0, DistanceToExit = -1;
9468 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9472 float MinsEarly = 0;
9473 TDateTime DepartureTime;
9474 TDateTime ArrivalTime;
9502 if(TempTTE < LastTimeToExit)
9537 if(TempTTE < LastTimeToExit)
9560 if(TempTTE < LastTimeToExit)
9590 if(TempTTE < LastTimeToExit)
9613 if(TempTTE < LastTimeToExit)
9656 float CurrentStopTime;
9657 float LaterStopTime;
9658 float RecoverableTime;
9666 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9673 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9674 bool DistanceToExitSet = (DistanceToExit > -1);
9675 int GenericDistance = DistanceToRedSignal;
9676 if(DistanceToExitSet)
9678 GenericDistance = DistanceToExit;
9694 float TimeToSubtract, TotalStopTime;
9697 TimeToSubtract = RecoverableTime;
9740 if(CurrentStopTime > 0)
9742 TotalStopTime = CurrentStopTime + LaterStopTime;
9751 else if((MinsEarly > 0) && !
Stopped())
9753 TotalStopTime = LaterStopTime + MinsEarly;
9757 if(LaterStopTime == 0)
9759 TotalStopTime = CurrentStopTime;
9765 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9768 if(AvTrackSpeed < 30)
9772 int Speed = AvTrackSpeed;
9782 if(DistanceToRedSignalSet)
9784 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9794 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9823 if((NextEntryPos == 0) || (NextEntryPos == 2))
9950 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9992 int IncrementalMinutes = 0;
9993 int IncrementalDigits = 0;
10001 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10036 if(AVEntry0.
Command ==
"Snt-sh")
10041 int IncrementalMinutes = 0;
10042 int IncrementalDigits = 0;
10050 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10093 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10173 AnsiString Loc =
"";
10174 bool ElementFound =
false;
10179 ElementFound =
true;
10184 ElementFound =
true;
10189 ElementFound =
true;
10218 else if(AVEntryPtr->
Command ==
"Fer")
10220 bool CorrectExit =
false;
10227 CorrectExit =
true;
10332 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10350 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10365 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10376 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10377 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10378 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10380 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10381 "," + AnsiString(Mass) +
"," + ModeStr);
10383 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10385 int RearExitPos = -1;
10387 for(
int x = 0; x < 4; x++)
10394 if(RearExitPos == -1)
10396 throw Exception(
"Error, RearExit == -1 in AddTrain");
10398 bool ReportFlag =
true;
10403 ReportFlag =
false;
10415 if(ModeStr ==
"Timetable")
10421 if(MaxRunningSpeed < 10)
10423 MaxRunningSpeed = 10;
10425 if(SignallerSpeed < 10)
10427 SignallerSpeed = 10;
10429 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10430 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10437 if(SignallerControl)
10467 if(!SignallerControl)
10482 if(!SignallerControl)
10493 AnsiString Loc =
"";
10510 if(!SignallerControl)
10529 int RouteNumber = -1;
10530 bool SignalsSet =
false;
10537 int RouteStartPosition;
10541 if(FirstPair.first == RouteNumber)
10543 RouteStartPosition = FirstPair.second;
10545 else if(SecondPair.first == RouteNumber)
10547 RouteStartPosition = SecondPair.second;
10551 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10557 else if(RouteNumber > -1)
10577 int LinkedRouteNumber = -1;
10598 int RouteStartPosition;
10602 if(FirstPair.first == RouteNumber)
10604 RouteStartPosition = FirstPair.second;
10606 else if(SecondPair.first == RouteNumber)
10608 RouteStartPosition = SecondPair.second;
10612 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10618 else if(RouteNumber > -1)
10638 int LinkedRouteNumber = -1;
10659 AnsiString(TrackVectorNumber));
10662 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10671 throw Exception(
"Error, VecPos not set in EntryPos");
10673 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10678 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10683 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10697 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10705 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10715 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10736 return(RepeatTime);
10745 AnsiString RetStr =
"", PartStr =
"";
10753 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10761 if(Ptr->SignallerControl)
10763 RetStr =
"Train under signaller control";
10768 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10779 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10783 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10787 else if(Ptr->FormatType ==
PassTime)
10791 else if(Ptr->Command ==
"Fns")
10797 else if(Ptr->Command ==
"F-nshs")
10800 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10807 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10814 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10817 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10820 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10827 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10829 PartStr =
"Terminate at " + Ptr->LocationName;
10831 else if(Ptr->Command ==
"Frh")
10833 PartStr =
"Terminate at " + Ptr->LocationName;
10835 else if(Ptr->Command ==
"Fer")
10837 AnsiString AllowedExits;
10841 else if(Ptr->Command ==
"Fjo")
10844 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10846 else if(Ptr->Command ==
"jbo")
10849 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10851 else if(Ptr->Command ==
"fsp")
10856 else if(Ptr->Command ==
"rsp")
10861 else if(Ptr->Command ==
"cdt")
10865 else if(Ptr->Command ==
"dsc")
10871 RetStr = RetStr +
'\n' + PartStr;
10879 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10892 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10893 AnsiString DepTime =
"", EventTime =
"";
10894 bool CDTFlag =
false;
10896 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10897 AnsiString TowardsLocation =
"";
10900 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10902 TowardsLocation = AVI->LocationName;
10904 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10913 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10919 if(AVI->Command ==
"cdt")
10921 CDTFlag = !CDTFlag;
10924 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10927 RetStr +=
"\nNew service splits at " + EventTime;
10931 if(AVI->Command ==
"jbo")
10934 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10938 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10941 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10945 if(AVI->Command ==
"Fjo")
10948 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at " + EventTime;
10952 if(AVI->Command ==
"Frh")
10954 RetStr +=
"\nNew service finishes and remains at location.";
10958 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10963 if(TowardsLocation !=
"")
10965 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10969 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10974 if(TowardsLocation !=
"")
10976 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10980 RetStr +=
"\nNew service departs at " + DepTime;
11145 ActiveTrackElementNameMapEntry.second = 0;
11151 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11154 if(TTBLFile.is_open())
11156 char *TrainTimetableString =
new char[10000];
11158 bool EndOfFile =
false;
11161 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11163 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11170 delete[] TrainTimetableString;
11174 AnsiString OneLine(TrainTimetableString);
11175 bool FinalCallFalse =
false;
11176 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11180 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11181 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11186 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11188 delete[] TrainTimetableString;
11192 OneLine = AnsiString(TrainTimetableString);
11198 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11200 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11210 OneLine = AnsiString(TrainTimetableString);
11212 if(OneLine.Length() > 9999)
11214 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11216 delete[] TrainTimetableString;
11220 bool FinalCallFalse =
false;
11221 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11225 delete[] TrainTimetableString;
11229 if(EndOfFile && (Count < 2))
11232 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11234 delete[] TrainTimetableString;
11240 delete[] TrainTimetableString;
11245 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11256 bool CheckLocationsExistInRailway)
11384 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11394 if(OneLine[1] !=
'*')
11396 int SCPos = OneLine.Pos(
';');
11407 bool AllCommas =
true;
11409 for(
int x = 1; x < OneLine.Length() + 1; x++)
11411 if(OneLine[x] !=
',')
11416 if(AllCommas || (OneLine ==
""))
11431 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11432 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11433 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11434 TDateTime StartTime(0);
11436 bool Warning =
false;
11463 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11464 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11465 double MaxBrakeRate = 0;
11466 double PowerAtRail = 0;
11467 int SignallerSpeed = 0;
11468 if(OneLine[1] ==
'*')
11474 int Pos = OneLine.Pos(
',');
11477 int SubStringLength = 20;
11478 if(OneLine.Length() < 20)
11480 SubStringLength = OneLine.Length();
11482 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11486 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11487 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11498 TempTrainDataEntry.
HeadCode = HeadCode;
11502 if(Description !=
"")
11507 TempTrainDataEntry.
Mass = Mass;
11515 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11518 while(NewRemainder[NewRemainder.Length()] ==
',')
11520 if(NewRemainder.Length() > 1)
11522 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11531 if(NewRemainder ==
"")
11533 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11538 int CommaCount = 0;
11539 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11541 if(NewRemainder[x] ==
',')
11546 if(CommaCount == 0)
11548 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11550 int SubStringLength = 20;
11551 if(OneLine.Length() < 20)
11553 SubStringLength = OneLine.Length();
11556 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11557 OneLine.SubString(1, SubStringLength) +
"'....");
11562 AnsiString OneEntry =
"";
11567 bool FinishFlag =
false;
11568 bool NewTrain =
false;
11569 for(
int x = 0; x < CommaCount + 1; x++)
11571 if((CommaCount == 0) || (x < CommaCount))
11576 if(CommaCount == 0)
11578 OneEntry = NewRemainder;
11583 Pos = NewRemainder.Pos(
',');
11584 OneEntry = NewRemainder.SubString(1, Pos - 1);
11585 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11591 RearStartOrRepeatMins = 0;
11592 FrontStartOrRepeatDigits = 0;
11593 NumberOfRepeats = 0;
11594 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11595 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11597 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11601 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11606 if(Warning && (Second ==
"Frh"))
11608 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11612 if(Warning && (Second ==
"Fjo"))
11615 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11621 if(NewTrain && (PowerAtRail < 1) && (Second ==
"jbo"))
11624 "': a train created without power can't 'be joined by' another train (i.e. can't include command 'jbo'), "
11625 "use command 'Fjo' (i.e. 'join' another train) instead immediately after the line containing 'Snt', and use "
11626 "command 'jbo' for the train it is to join.");
11630 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"fsp") || (Second ==
"rsp")))
11633 "': a train created without power can't split.");
11637 if(NewTrain && (PowerAtRail < 1) && (Second ==
"cdt"))
11640 "': a train created without power can't change direction under timetable control.");
11649 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11653 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11655 if(NewRemainder[1] !=
'R')
11658 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11664 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11668 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11671 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11677 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11682 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11687 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11690 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11706 TDateTime TempTime;
11712 ActionVectorEntry.
Warning = Warning;
11728 ActionVectorEntry.
Command = Second;
11743 else if(FormatType ==
TimeCmd)
11749 ActionVectorEntry.
Command = Second;
11757 ActionVectorEntry.
Command = Second;
11758 ActionVectorEntry.
ExitList = ExitList;
11766 ActionVectorEntry.
Command = Second;
11780 ActionVectorEntry.
Command = Second;
11791 ActionVectorEntry.
Command = Second;
11801 ActionVectorEntry.
Command = Second;
11803 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
11814 ActionVectorEntry.
Command = Second;
11823 ActionVectorEntry.
Command = Second;
11829 ActionVectorEntry.
Command = Second;
11837 ActionVectorEntry.
Command = Second;
11840 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11845 OneEntry = NewRemainder;
11850 RearStartOrRepeatMins = 0;
11851 FrontStartOrRepeatDigits = 0;
11852 NumberOfRepeats = 0;
11853 if((FinishFlag) && (OneEntry[1] !=
'R'))
11856 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11860 if(OneEntry[1] !=
'R')
11862 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11863 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11865 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11870 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"Fns") || (Second ==
"Frh-sh") || (Second ==
"Fns-sh") || (Second ==
"F-nshs")))
11873 "': a train created without power can't form a new service.");
11880 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11887 TDateTime TempTime;
11893 ActionVectorEntry.
Warning = Warning;
11900 ActionVectorEntry.
Command = Second;
11908 ActionVectorEntry.
Command = Second;
11917 ActionVectorEntry.
Command = Second;
11926 ActionVectorEntry.
Command = Second;
11936 ActionVectorEntry.
Command = Second;
11937 ActionVectorEntry.
ExitList = ExitList;
11941 ActionVectorEntry.
Command = Second;
11943 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11948 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11964 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11983 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11988 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12003 if(TimeStr.Length() < 5)
12008 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12013 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12018 if(TimeStr[3] !=
':')
12023 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12028 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12033 while(TimeStr.Length() > 5)
12035 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12037 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12038 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12040 if((WholeHours + FracHour) >= 95.98334)
12045 Time = TDateTime((WholeHours + FracHour) / 24);
12052 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
12053 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12062 TDateTime TempTime;
12064 if(OneEntry.Length() > 0)
12066 if(OneEntry[1] ==
'W')
12069 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
12073 if(OneEntry ==
"Frh")
12083 if(OneEntry.Length() < 7)
12088 int Pos = OneEntry.Pos(
';');
12096 First = OneEntry.SubString(1, 5);
12102 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
12104 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
12107 if(Remainder.Length() < 7)
12112 Pos = Remainder.Pos(
';');
12119 Second = Remainder.SubString(1, 5);
12125 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12138 Pos = Remainder.Pos(
';');
12141 Second = Remainder;
12142 if(Second ==
"cdt")
12167 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12173 Second = Remainder.SubString(1, Pos - 1);
12175 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12177 Pos = Remainder.Pos(
';');
12184 Third = Remainder.SubString(1, Pos - 1);
12185 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12188 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12191 int SpacePos = Third.Pos(
' ');
12197 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12198 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12200 if(CheckLocationsExistInRailway)
12210 if(Second ==
"Snt")
12233 if(Second ==
"Sns-sh")
12252 if(Second ==
"F-nshs")
12266 if(Second ==
"Sns-fsh")
12280 if(Second ==
"Fns-sh")
12300 if(Second ==
"pas")
12315 if(Second ==
"Fer")
12322 if(CheckLocationsExistInRailway)
12333 if(Second ==
"dsc")
12335 if(Third.Length() > 60)
12337 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12341 for(
int x = 1; x < Third.Length() + 1; x++)
12343 if((Third[x] <
' ') || (Third[x] >
'~'))
12345 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12361 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12362 (Second !=
"Frh-sh"))
12374 if(Second ==
"Frh-sh")
12382 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12386 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12390 if((Second ==
"Sfs") || (Second ==
"Sns"))
12395 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12412 bool ErrorFlag =
false;
12414 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12418 int pos = SplitDistributionString.Pos(
'-');
12425 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12426 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12429 int x = MassStr.ToInt();
12430 int y = PowerStr.ToInt();
12431 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12436 catch(
const Exception &e)
12443 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12444 "power for the new split-off train");
12464 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
12469 for(
int x = 1; x < LocStr.Length() + 1; x++)
12471 if(LocStr[x] <
' ')
12476 if(LocStr[x] >
'z')
12483 if(CheckLocationsExistInRailway)
12488 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12489 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12490 "that includes a continuation will not be valid.");
12508 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12511 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12516 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12518 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12520 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12526 for(
int x = 3; x >= 0; x--)
12528 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12529 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12531 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12547 AnsiString CurrentID =
"";
12549 if(IDSet.Length() == 0)
12551 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12555 for(
int x = 1; x <= IDSet.Length(); x++)
12558 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12560 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12582 int Pos = IDSet.Pos(
' ');
12593 CurrentID = IDSet.SubString(1, Pos - 1);
12594 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12606 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12613 if(!ExitList.empty())
12615 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12617 if(*ELIT == VecPos)
12619 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12626 ExitList.push_back(VecPos);
12636 Pos = IDSet.Pos(
' ');
12643 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12650 AnsiString Remainder =
"";
12651 int SemiColonCount = 0;
12653 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12655 if(TrainInfoStr[x] ==
';')
12660 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12662 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12663 "'. Should be headcode + optional description for a continuing service;" +
12664 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12668 if(SemiColonCount == 0)
12670 HeadCode = TrainInfoStr;
12679 if(SemiColonCount == 1)
12681 Pos = TrainInfoStr.Pos(
';');
12682 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12683 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12689 if(Description ==
"")
12691 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12695 if(Description.Length() > 60)
12697 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12701 for(
int x = 1; x < Description.Length() + 1; x++)
12703 if((Description[x] <
' ') || (Description[x] >
'~'))
12705 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12714 Pos = TrainInfoStr.Pos(
';');
12715 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12716 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12722 Pos = Remainder.Pos(
';');
12723 Description = Remainder.SubString(1, Pos - 1);
12724 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12725 if(Description ==
"")
12727 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12731 if(Description.Length() > 60)
12733 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12737 for(
int x = 1; x < Description.Length() + 1; x++)
12739 if((Description[x] <
' ') || (Description[x] > 126))
12741 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12746 Pos = Remainder.Pos(
';');
12747 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12749 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12750 if(StartSpeedStr ==
"")
12752 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12756 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12758 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12760 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12765 StartSpeed = StartSpeedStr.ToInt();
12771 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12775 Pos = Remainder.Pos(
';');
12776 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12778 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12779 if(MaxRunningSpeedStr ==
"")
12781 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12785 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12787 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12789 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12794 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12800 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12804 if(MaxRunningSpeed < 10)
12807 MaxRunningSpeed = 10;
12810 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12814 Pos = Remainder.Pos(
';');
12815 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12817 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12820 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12824 for(
int x = 1; x < MassStr.Length() + 1; x++)
12826 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12828 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12833 Mass = MassStr.ToInt() * 1000;
12839 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12845 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12849 Pos = Remainder.Pos(
';');
12850 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12852 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12853 if(MaxBrakeForceStr ==
"")
12855 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12859 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12861 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12863 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12868 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12871 if((MaxBrakeForce / Mass) > 1)
12873 MaxBrakeForce = Mass;
12876 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12880 if((MaxBrakeForce / Mass) < 0.01)
12882 MaxBrakeForce = Mass * 0.01;
12885 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12890 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12892 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12894 if(SemiColonCount == 6)
12896 GrossPowerStr = Remainder;
12897 SignallerSpeedStr =
"30";
12901 Pos = Remainder.Pos(
';');
12902 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12903 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12906 if(GrossPowerStr ==
"")
12908 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12912 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12914 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12916 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12922 double GrossPower = GrossPowerStr.ToInt() * 1000;
12929 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12933 else if(GrossPower == 0)
12938 else if((GrossPower > 0) && (GrossPower < 10000))
12941 GrossPower = 10000;
12943 PowerAtRail = GrossPower * 0.8;
12947 if(SignallerSpeedStr ==
"")
12949 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12953 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12955 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12957 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12962 SignallerSpeed = SignallerSpeedStr.ToInt();
12968 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12972 if(SignallerSpeed < 10)
12975 SignallerSpeed = 10;
12978 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12996 if(OneEntry.Length() < 7)
12998 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13002 int SemiColonCount = 0;
13004 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13006 if(OneEntry[x] ==
';')
13011 if(SemiColonCount != 3)
13013 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13017 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13019 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13023 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13028 Pos = Remainder.Pos(
';');
13029 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13031 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13032 if(MinutesStr ==
"")
13034 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13038 if(MinutesStr.Length() > 3)
13041 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13045 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13047 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13049 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13054 RearStartOrRepeatMins = MinutesStr.ToInt();
13055 if(RearStartOrRepeatMins == 0)
13057 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13061 Pos = Remainder.Pos(
';');
13062 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13064 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13065 if(DigitsStr ==
"")
13067 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13071 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13073 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13075 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13080 if(DigitsStr.Length() > 2)
13082 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13086 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13100 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13104 AnsiString NumberStr = Remainder;
13106 if(NumberStr ==
"")
13108 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13112 if(NumberStr.Length() > 4)
13115 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13119 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13121 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13124 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13129 NumberOfRepeats = NumberStr.ToInt();
13130 if(NumberOfRepeats == 0)
13132 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13304 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13325 TwoLocationFlag =
false;
13331 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13345 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13361 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13373 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13399 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13412 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after an 'Sns' or 'Sfs' event for: " +
13419 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13425 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13435 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13440 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13450 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13455 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13465 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13476 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13486 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13498 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13505 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13514 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13533 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13535 AnsiString LocationName =
"";
13549 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13550 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13559 if(AVEntry0.
Command ==
"Snt-sh")
13573 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13589 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13590 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13602 bool FoundFlag =
false;
13606 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13608 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13620 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13633 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13658 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13680 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13702 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13727 bool LocFoundFlag, FnsFoundFlag;
13731 LocFoundFlag =
false;
13732 FnsFoundFlag =
false;
13733 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13738 FnsFoundFlag =
true;
13747 LocFoundFlag =
true;
13758 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13764 if(FnsFoundFlag && !LocFoundFlag)
13766 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13779 if(AVEntry0.
Command ==
"Sns")
13791 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13799 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13800 ". The event isn't valid for a stationary train.");
13808 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13815 TDateTime SnsEventTime = AVEntry0.
EventTime;
13818 bool BreakFlag =
false;
13821 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13826 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13848 if(AVEntry0.
Command ==
"Sfs")
13850 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13858 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13870 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13875 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13895 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13902 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13917 if(AVEntry0.
Command ==
"Sfs")
13929 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13937 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13938 ". The event isn't valid for a stationary train.");
13946 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13953 TDateTime SfsEventTime = AVEntry0.
EventTime;
13955 bool BreakFlag =
false;
13958 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13963 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
13983 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13988 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14009 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14016 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14021 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
14024 "Please make sure that the finish event of the service that links to this event is preceded by an "
14025 "event at the same location that has an identified location name, normally an arrival.");
14030 else if(AVEntry.
Command ==
"Snt-sh")
14033 "Please make sure that the service starts with zero speed and is at a named location.");
14038 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
14041 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
14048 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14061 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14071 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
14078 if(AVEntry.
Command ==
"F-nshs")
14083 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14111 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14112 ". The event isn't valid for a stationary train.");
14122 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14130 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14131 ". The event isn't valid for a stationary train.");
14149 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14150 ". The event isn't valid for a stationary train.");
14168 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14169 ". The event isn't valid for a stationary train.");
14179 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14187 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14188 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14206 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14207 ". The event isn't valid for a moving train.");
14229 bool LastEntryIsAnArrival =
false;
14236 LastEntryIsAnArrival =
false;
14237 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14244 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14246 if(LastEntryIsAnArrival)
14250 LastEntryIsAnArrival =
false;
14256 LastEntryIsAnArrival =
true;
14263 LastEntryIsAnArrival =
true;
14264 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14271 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14273 if(LastEntryIsAnArrival)
14277 LastEntryIsAnArrival =
false;
14283 LastEntryIsAnArrival =
true;
14293 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14301 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14309 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14310 ". The event isn't valid for a stationary train.");
14321 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14329 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14330 ". The event isn't valid for a moving train.");
14344 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14351 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14355 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14362 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14366 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14375 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14379 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14386 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14397 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14412 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14420 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14435 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14447 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14459 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14460 ", may be before timetable start time");
14471 AnsiString LastLocationName =
"";
14475 bool LastEntryIsAnArrival =
false;
14480 LastEntryIsAnArrival =
false;
14481 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14482 if(LastLocationName !=
"")
14484 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14486 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14499 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14511 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14524 TwoLocationFlag =
true;
14529 LastEntryIsAnArrival =
false;
14533 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14536 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14541 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14544 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14550 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14556 LastEntryIsAnArrival =
true;
14557 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14558 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14570 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14582 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14595 TwoLocationFlag =
true;
14600 LastEntryIsAnArrival =
false;
14604 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14607 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14615 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14622 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14630 AnsiString LocationNameToBeChecked =
"";
14635 unsigned int y = 0;
14649 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14650 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14668 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14677 TwoLocationFlag =
true;
14688 if(TwoLocationFlag)
14698 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14703 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14705 AnsiString LocName =
"";
14711 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14718 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14741 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14766 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14788 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14810 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14829 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14832 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14847 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14852 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14856 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14860 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14864 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14903 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14905 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14911 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14924 int IncMinutes = 0;
14934 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14940 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14946 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14951 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14957 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14962 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14975 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15001 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
15009 if(HeadCode.Length() > 4)
15011 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15022 int ForwardCount = 0;
15023 int ReverseCount = 0;
15025 if(MainHeadCode == SecondHeadCode)
15027 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15036 if(TDEntry.
HeadCode == MainHeadCode)
15038 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15053 if(ForwardCount == 0)
15056 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15058 if(ForwardCount > 2)
15061 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15062 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15071 if(TDEntry.
HeadCode == SecondHeadCode)
15073 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15088 if(ReverseCount == 0)
15090 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15095 if(ReverseCount > 2)
15098 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15099 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15104 if(ForwardCount != ReverseCount)
15106 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15107 " than the other way round");
15138 int ForwardCount = 0;
15139 int ReverseCount = 0;
15140 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15149 if(TDEntry.
HeadCode == MainHeadCode)
15151 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15154 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15159 ForwardEntryPtr = &AVEntry;
15161 ForwardTDVectorNumber = x;
15164 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15165 (AVEntry.
Command ==
"Frh-sh")))
15170 ForwardEntryPtr = &AVEntry;
15172 ForwardTDVectorNumber = x;
15178 if(ForwardCount == 0)
15181 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15183 if(ForwardCount > 1)
15185 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15195 if(TDEntry.
HeadCode == OtherHeadCode)
15197 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15200 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15206 ReverseEntryPtr = &AVEntry;
15207 ReverseTDVectorNumber = x;
15210 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15216 ReverseEntryPtr = &AVEntry;
15217 ReverseTDVectorNumber = x;
15224 if(ReverseCount == 0)
15226 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15231 if(ReverseCount > 1)
15233 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15240 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15241 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15242 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15243 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15247 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15254 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15259 if(SetDataAndCheckLocations)
15261 if(ForwardEntryPtr->LocationName ==
"")
15263 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15264 ". One or other service does not have a location set");
15271 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15272 ". One or other service does not have a location set");
15277 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15279 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15280 " is at a different location to the referencing train " + MainHeadCode);
15289 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15291 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15292 " has a different event time to the referencing train " + MainHeadCode);
15300 if(ForwardShuttleStart && ReverseShuttleFinish)
15305 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15306 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15312 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15315 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15317 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15318 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15324 if(ReverseEntryPtr->
Command ==
"Fjo")
15327 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15329 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15330 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15336 if(ReverseEntryPtr->
Command ==
"Fns")
15339 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15341 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15342 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15348 if(ForwardEntryPtr->Command ==
"Sfs")
15350 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15353 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15360 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15362 if(ReverseEntryPtr->
Command !=
"Sfs")
15364 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15372 if(SetDataAndCheckLocations)
15376 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15383 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15390 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15395 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15407 if(ForwardEntryPtr->Command ==
"Sns")
15409 if(ReverseEntryPtr->
Command !=
"Fns")
15411 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15412 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15418 if(ForwardEntryPtr->Command ==
"Fns")
15420 if(ReverseEntryPtr->
Command !=
"Sns")
15422 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15423 " and forms a new service with headcode " + OtherHeadCode);
15430 if(SetDataAndCheckLocations)
15432 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15444 if(ForwardEntryPtr->Command ==
"jbo")
15446 if(ReverseEntryPtr->
Command !=
"Fjo")
15448 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15449 " and is joined by a train with headcode " + OtherHeadCode);
15455 if(ForwardEntryPtr->Command ==
"Fjo")
15457 if(ReverseEntryPtr->
Command !=
"jbo")
15459 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15460 " and joins a train with headcode " + OtherHeadCode);
15467 if(SetDataAndCheckLocations)
15469 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15485 if(ForwardShuttleStart)
15488 if(!ReverseShuttleFinish)
15491 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15492 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15498 if(ReverseShuttleStart)
15501 if(!ForwardShuttleFinish)
15504 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15505 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15512 if(SetDataAndCheckLocations)
15514 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15527 bool MainRepeat =
false, OtherRepeat =
false;
15537 OtherRepeat =
true;
15540 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15542 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15543 " and the associated train with headcode " + OtherHeadCode);
15548 if(MainRepeat && OtherRepeat)
15554 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15555 " and the associated train with headcode " + OtherHeadCode);
15577 while(Input[1] ==
' ')
15579 if(Input.Length() > 1)
15581 Input = Input.SubString(2, Input.Length() - 1);
15595 while(Input[Input.Length()] ==
' ')
15597 if(Input.Length() > 1)
15599 Input = Input.SubString(1, Input.Length() - 1);
15609 AnsiString Output =
"";
15610 bool DelimiterFound =
false;
15612 for(
int x = 1; x < Input.Length() + 1; x++)
15616 if(Input[x] ==
' ')
15621 if((Input[x] !=
',') && (Input[x] !=
';'))
15623 DelimiterFound =
false;
15624 Output = Output + Input[x];
15628 DelimiterFound =
true;
15629 Output = Output + Input[x];
15641 DelimiterFound =
false;
15642 for(
int x = Input.Length(); x > 0; x--)
15646 if(Input[x] ==
' ')
15651 if((Input[x] !=
',') && (Input[x] !=
';'))
15653 DelimiterFound =
false;
15654 Output = AnsiString(Input[x]) + Output;
15658 DelimiterFound =
true;
15659 Output = AnsiString(Input[x]) + Output;
15684 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15686 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15698 LocationName = LocRear;
15702 LocationName = LocFront;
15704 if(LocationName ==
"")
15725 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15766 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
15769 if(RearPosition < 0)
15776 if(FrontPosition < 0)
15787 for(
int x = 0; x < 4; x++)
15789 if(RearTrackElement.
Conn[x] == FrontPosition)
15804 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15811 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15817 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15822 if((RearType ==
Points) && (RearExitPos == 3))
15824 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
15830 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
15845 AnsiString(RearExitPos));
15856 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15858 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15861 AnsiString RearName, FrontName;
15877 FrontName = FrontTrackElement.
ElementID;
15880 int LockedVectorNumber;
16050 "," + AnsiString(IncDigits));
16053 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16058 return(BaseHeadCode);
16060 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16061 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16063 while(NextRepeatDigits >= 100)
16065 NextRepeatDigits -= 100;
16067 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16069 if(NextRepeatDigitsStr.Length() < 2)
16071 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16073 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16076 return(NextRepeatHeadCode);
16084 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16085 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16087 return(NextRepeatTime);
16096 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16097 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16098 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16099 int RepeatSecs = RepeatMinutes * 60;
16101 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16135 NonRepeatingHeadCode);
16136 int ForwardCount = 0;
16137 int ReverseCount = 0;
16138 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16148 if(TDEntry.
HeadCode == MainHeadCode)
16150 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16156 ForwardEntryPtr = &AVEntry;
16158 ForwardTDVectorNumber = x;
16163 if(ForwardCount == 0)
16166 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16168 if(ForwardCount > 1)
16170 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16180 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16182 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16189 ReverseEntryPtr = &AVEntry;
16190 ReverseTDVectorNumber = x;
16196 if(ReverseCount == 0)
16198 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16203 if(ReverseCount > 1)
16205 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16206 NonRepeatingHeadCode);
16211 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16213 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16218 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16220 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16225 if(SetDataAndCheckLocations)
16227 if(ForwardEntryPtr->LocationName ==
"")
16229 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16230 ". One or other service does not have a location set");
16237 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16238 ". One or other service does not have a location set");
16243 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16245 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16246 " is at a different location to the referencing train " + MainHeadCode);
16252 if(ForwardEntryPtr->Command ==
"F-nshs")
16255 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16257 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16258 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16264 if(ForwardEntryPtr->Command ==
"Fns-sh")
16268 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16270 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16271 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16277 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16280 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16282 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16283 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16301 if(ForwardEntryPtr->Command ==
"Sns-sh")
16303 if(ReverseEntryPtr->
Command !=
"F-nshs")
16305 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16306 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16312 if(ForwardEntryPtr->Command ==
"F-nshs")
16314 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16316 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16317 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16324 if(SetDataAndCheckLocations)
16326 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16338 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16340 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16343 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16344 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16350 if(ForwardEntryPtr->Command ==
"Fns-sh")
16352 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16355 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16356 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16363 if(SetDataAndCheckLocations)
16365 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16389 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16390 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16391 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16392 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16394 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16418 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16421 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16422 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16424 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16426 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16431 while(LastActionCommand ==
"Fns")
16433 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16434 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16435 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16438 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16439 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16446 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16449 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16450 ". The linking of two or more shuttles is not permitted.");
16488 ShowMessage(Message);
16497 int Mins = Input, Hrs = 0;
16503 AnsiString AnsiMins = AnsiString(Mins);
16504 if(AnsiMins.Length() == 1)
16506 AnsiMins =
"0" + AnsiMins;
16508 AnsiString AnsiHrs = AnsiString(Hrs);
16509 if(AnsiHrs.Length() == 1)
16511 AnsiHrs =
"0" + AnsiHrs;
16514 return(AnsiHrs +
':' + AnsiMins);
16554 AnsiString(ActionEventType) +
"," + LocationID);
16555 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16560 Prefix =
" ERROR: ";
16563 Prefix =
" HELD: ";
16564 ErrorLog =
" can't enter railway, train obstructing entry position ";
16565 WarningStr =
" can't enter railway, train obstructing entry position ";
16570 Prefix =
" HELD: ";
16571 ErrorLog =
" can't enter railway, route set against it at entry position ";
16572 WarningStr =
" can't enter railway, route set against it at entry position ";
16577 Prefix =
" HELD: ";
16578 ErrorLog =
" can't be created, train obstructing ";
16579 WarningStr =
" can't be created, train obstructing ";
16584 Prefix =
" HELD: ";
16585 ErrorLog =
" can't be created on a locked route at ";
16586 WarningStr =
" can't be created on a locked route at ";
16591 Prefix =
" HELD: ";
16592 ErrorLog =
" can't enter on a locked route at ";
16593 WarningStr =
" can't enter on a locked route at ";
16598 Prefix =
" HELD: ";
16599 ErrorLog =
" can't be created, diverging points at ";
16600 WarningStr =
" can't be created, diverging points at ";
16605 ErrorLog =
" left railway unexpectedly at ";
16610 ErrorLog =
" left railway at an incorrect exit at ";
16615 ErrorLog =
" failed to split - location too short at ";
16616 WarningStr =
" failed to split, location too short at ";
16621 Prefix =
" HELD: ";
16622 ErrorLog =
" unable to split - other train obstructing at ";
16623 WarningStr =
" unable to split - other train obstructing at ";
16628 ErrorLog =
" stopped at buffers unexpectedly at position ";
16632 ErrorLog =
" failed to stop at ";
16637 ErrorLog =
" failed to split at ";
16642 ErrorLog =
" failed to be joined by other train at ";
16647 ErrorLog =
" failed to change its description at ";
16652 ErrorLog =
" failed to join other train at ";
16657 ErrorLog =
" failed to terminate at ";
16662 ErrorLog =
" failed to form new service at ";
16667 ErrorLog =
" failed to exit railway ";
16672 ErrorLog =
" failed to change direction at ";
16677 ErrorLog =
" failed to pass ";
16682 ErrorLog =
" facing buffers and unable to start at ";
16686 ErrorLog =
" DERAILED at position ";
16687 Prefix =
" DERAILMENT: ";
16692 ErrorLog =
" CRASHED INTO BUFFERS at ";
16693 Prefix =
" CRASH: ";
16698 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16699 Prefix =
" CRASH: ";
16704 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16705 Prefix =
" CRASH: ";
16709 else if(ActionEventType ==
FailSPAD)
16711 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16712 Prefix =
" SPAD: ";
16717 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16718 Prefix =
" SPAD RISK: ";
16723 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16727 Prefix =
" WARNING: ";
16728 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16729 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16734 Prefix =
" WARNING: ";
16735 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16736 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16774 std::ofstream OutFile(
"TrainData.csv");
16778 ShowMessage(
"Output file TrainData.csv failed to open");
16785 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16790 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16791 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16792 "RepeatNumber" <<
'\n' <<
'\n';
16793 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16796 AnsiString TimetableEntryTypeStr;
16802 TimetableEntryTypeStr =
"NoFormat";
16808 TimetableEntryTypeStr =
"TimeLoc";
16814 TimetableEntryTypeStr =
"TimeTimeLoc";
16820 TimetableEntryTypeStr =
"TimeCmd";
16826 TimetableEntryTypeStr =
"StartNew";
16832 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16838 TimetableEntryTypeStr =
"FinRemHere";
16844 TimetableEntryTypeStr =
"FNSShuttle";
16850 TimetableEntryTypeStr =
"SNTShuttle";
16856 TimetableEntryTypeStr =
"SNSShuttle";
16862 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16868 TimetableEntryTypeStr =
"FSHNewService";
16874 TimetableEntryTypeStr =
"Repeat";
16880 TimetableEntryTypeStr =
"Default";
16891 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16892 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16895 AnsiString RunningEntryStr;
16901 RunningEntryStr =
"NotStarted";
16907 RunningEntryStr =
"Running";
16913 RunningEntryStr =
"Exited";
16917 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16934 ShowMessage(Message);
16935 BaseTime = TDateTime::CurrentDateTime();
16949 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16962 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16964 for(
int x = 0; x < NumberOfTrains; x++)
16966 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16986 int NumberOfTrains;
16993 for(
int x = 0; x < NumberOfTrains; x++)
17030 for(
int x = 0; x < LockedRouteVectorSize; x++)
17037 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17048 int LockedRouteVectorSize;
17055 for(
int x = 0; x < LockedRouteVectorSize; x++)
17113 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17121 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17132 int ContinuationAutoSigVectorSize;
17139 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17209 if(AVFirstEntry.
Command ==
"Snt")
17233 CTEMMP.second = CTEEntry;
17240 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17248 CTEMMP.second = CTEEntry;
17269 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17286 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17288 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17299 AnsiString RetStr =
"", PartStr =
"";
17414 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17418 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17420 AnsiString ShortTTName =
"";
17422 for(
int x = TTFileName.Length(); x > 0; x--)
17424 if(TTFileName[x] ==
'\\')
17426 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17431 ShowMessage(
"Creates two timetables named " + ShortTTName +
17432 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17434 Screen->Cursor = TCursor(-11);
17436 AnsiString FormatNoDPStr =
"#######0";
17437 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17440 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17447 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17449 if(TrainDataEntry.
Mass > 0)
17451 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17455 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17459 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17463 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17465 FirstHeadCode = TrainDataEntry.
HeadCode;
17466 int IncDigits = 0, IncMinutes = 0;
17468 if(!ActionVector.empty())
17470 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17472 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17473 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17481 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
17483 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
17491 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17496 AnsiString PartStr =
"", TimeStr =
"";
17513 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17517 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17527 PartStr =
"Enters at " + LocName;
17540 PartStr =
"Created at " + LocName;
17554 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17559 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17565 else if(ActionVectorEntry.
Command ==
"Sfs")
17567 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17571 else if(ActionVectorEntry.
Command ==
"Sns")
17573 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17581 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17587 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17595 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17598 AnsiString FirstHeadCode = TDE->
HeadCode;
17602 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17614 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17616 OneTTEntry.
Action = PartStr;
17617 OneTTEntry.
Time = TimeStr;
17619 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17624 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17630 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17635 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17643 else if(ActionVectorEntry.
Command ==
"jbo")
17645 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17649 else if(ActionVectorEntry.
Command ==
"fsp")
17653 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17657 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17662 else if(ActionVectorEntry.
Command ==
"rsp")
17666 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17670 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17675 else if(ActionVectorEntry.
Command ==
"cdt")
17677 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17680 else if(ActionVectorEntry.
Command ==
"dsc")
17682 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17688 if(ActionVectorEntry.
Command ==
"Fns")
17690 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17694 else if(ActionVectorEntry.
Command ==
"F-nshs")
17696 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17702 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17709 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17715 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17722 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17727 else if(ActionVectorEntry.
Command ==
"Frh")
17729 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17734 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17738 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17748 else if(ActionVectorEntry.
Command ==
"Fer")
17750 AnsiString AllowedExits;
17754 else if(ActionVectorEntry.
Command ==
"Fjo")
17756 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17765 OneTTEntry.
Action = PartStr;
17766 OneTTEntry.
Time = TimeStr;
17773 AllTTTrains->push_back(OneTTLine);
17777 std::ofstream TTFile(TTFileName.c_str());
17781 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17782 delete AllTTTrains;
17817 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17818 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17820 TTFile << AllTTTrains->at(x).Header.c_str();
17823 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17825 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17827 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17831 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17834 TTFile <<
'\n' <<
'\n';
17836 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17838 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17839 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17841 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17843 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17847 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17852 TTFile <<
'\n' <<
'\n';
17857 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17859 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17861 std::ofstream TTFile2(TTFileName2.c_str());
17865 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17866 delete AllTTTrains;
17870 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17871 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17872 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17874 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17879 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17880 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17882 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17884 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17886 bool GiveMessagesFalse =
false;
17887 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17888 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17889 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17894 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17895 TimeString = TimeString.SubString(9, 5);
17896 ActionString +=
" " + OtherHeadCode;
17898 if(TimeString.SubString(1, 7) ==
"End at ")
17901 TimeString = TimeString.SubString(8, 5);
17903 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17904 AnsiMultiMapEntry.first = TimeString;
17905 AnsiMultiMapEntry.second = OneLine;
17906 TAMM->insert(AnsiMultiMapEntry);
17911 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17913 TTFile2 << (AMMIT->second).c_str();
17915 delete AllTTTrains;
17924 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17928 bool AnalysisError =
false;
17929 AnsiString SequenceLog =
"SequenceLog\n";
17972 TTrainDataVector::iterator TDVIt, TDVCopyIt;
17974 int IteratorNumber = 0;
17975 AnsiString AnsiSuffix =
"";
17982 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
17985 AnsiSuffix = AnsiString(Suffix);
17986 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
17987 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
17993 int Increment = 0, SlashPos;
17995 AnsiString LinkedHeadCode;
17999 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
18001 if(AVEIt->LinkedTrainEntryPtr != NULL)
18010 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18012 if(LinkedHeadCode[x] ==
'/')
18014 SlashPos = LinkedHeadCode.Length() - x + 1;
18017 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18018 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18019 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18025 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18029 AVEIt->OtherHeadCode =
"";
18031 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18033 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18037 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18040 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18042 if(LinkedHeadCode[x] ==
'/')
18044 SlashPos = LinkedHeadCode.Length() - x + 1;
18047 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18048 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18049 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18055 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18059 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18064 SequenceLog +=
"1\n";
18067 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18073 ServiceCallingLocsList.clear();
18074 if(ActionVector.empty())
18078 if(ActionVector.at(0).SignallerControl)
18082 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18100 int HLoc = TE.
HLoc;
18101 int VLoc = TE.
VLoc;
18102 AnsiString HString;
18103 AnsiString VString;
18106 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18110 HString = AnsiString(HLoc);
18114 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18118 VString = AnsiString(VLoc);
18120 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18143 else if(AVE.
Command ==
"cdt")
18156 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18165 ServiceCallingLocsList.push_back(LName);
18169 int HLoc = TE.
HLoc;
18170 int VLoc = TE.
VLoc;
18171 AnsiString HString;
18172 AnsiString VString;
18175 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18179 HString = AnsiString(HLoc);
18183 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18187 VString = AnsiString(VLoc);
18189 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18193 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18197 SequenceLog +=
"2\n";
18226 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18232 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18233 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18234 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18236 SequenceLog +=
"3\n";
18243 TDateTime LastTDTime;
18244 int IncMinutes = 0;
18246 if(ActionVector.empty())
18250 if(ActionVector.at(0).SignallerControl)
18254 if(AVLast->FormatType ==
Repeat)
18256 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18264 if(AVLast->ArrivalTime != TDateTime(-1))
18266 LastTDTime = AVLast->ArrivalTime;
18268 else if(AVLast->EventTime != TDateTime(-1))
18270 LastTDTime = AVLast->EventTime;
18289 SequenceLog +=
"4\n";
18326 int IncMinutes = 0;
18328 if(ActionVector.empty())
18332 if(ActionVector.at(0).SignallerControl)
18336 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18338 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18340 for(
int y = 0; y < NumTrains; y++)
18354 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18369 LocServiceTimesVector.push_back(TLSTEntry);
18372 AnsiString IncTime =
"", FoundStopTime =
"";
18373 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18375 if(ActionVector.at(a).FormatType ==
TimeLoc)
18386 if(FoundStopTime ==
"")
18388 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18390 int WhileCount = 0;
18399 if(IncTime >= FoundStopTime)
18403 LocServiceTimesVector.push_back(TLSTEntry);
18404 if(WhileCount > 2000)
18406 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18419 int HLoc = TE.
HLoc;
18420 int VLoc = TE.
VLoc;
18421 AnsiString HString;
18422 AnsiString VString;
18425 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18429 HString = AnsiString(HLoc);
18433 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18437 VString = AnsiString(VLoc);
18439 TLSTEntry.
Location = HString +
'-' + VString;
18443 LocServiceTimesVector.push_back(TLSTEntry);
18451 LocServiceTimesVector.push_back(TLSTEntry);
18453 AnsiString IncTime =
"", FoundStopTime =
"";
18454 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18456 if(ActionVector.at(a).FormatType ==
TimeLoc)
18467 if(FoundStopTime ==
"")
18469 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18471 int WhileCount = 0;
18480 if(IncTime >= FoundStopTime)
18484 LocServiceTimesVector.push_back(TLSTEntry);
18485 if(WhileCount > 2000)
18487 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18497 bool SkipAddingMinutes =
false;
18500 LocServiceTimesVector.push_back(TLSTEntry);
18502 AnsiString IncTime =
"", FoundStopTime =
"";
18503 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18505 if(ActionVector.at(a).FormatType ==
TimeLoc)
18513 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18517 LocServiceTimesVector.pop_back();
18518 SkipAddingMinutes =
true;
18523 if(FoundStopTime ==
"")
18525 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18527 if(!SkipAddingMinutes)
18529 int WhileCount = 0;
18538 if(IncTime >= FoundStopTime)
18542 LocServiceTimesVector.push_back(TLSTEntry);
18543 if(WhileCount > 2000)
18545 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18554 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18556 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18558 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18559 LocServiceTimesVector.pop_back();
18560 LocServiceTimesVector.push_back(TLSTEntry);
18565 LocServiceTimesVector.push_back(TLSTEntry);
18571 LocServiceTimesVector.push_back(TLSTEntry);
18590 LocServiceTimesVector.push_back(TLSTEntry);
18594 AnsiString TempDepTime = TLSTEntry.
DepTime;
18596 LocServiceTimesVector.push_back(TLSTEntry);
18598 while(TLSTEntry.
AtLocTime < TempDepTime)
18603 TLSTEntry.
DepTime = TempDepTime;
18604 LocServiceTimesVector.push_back(TLSTEntry);
18608 LocServiceTimesVector.push_back(TLSTEntry);
18619 LocServiceTimesVector.push_back(TLSTEntry);
18622 LocServiceTimesVector.push_back(TLSTEntry);
18639 AnsiString HString;
18640 AnsiString VString;
18643 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18647 HString = AnsiString(HLoc);
18651 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18655 VString = AnsiString(VLoc);
18657 TLSTEntry.
Location = HString +
'-' + VString;
18659 LocServiceTimesVector.push_back(TLSTEntry);
18664 AnsiString FrhTime;
18665 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18669 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18677 LocServiceTimesVector.push_back(TLSTEntry);
18683 LocServiceTimesVector.push_back(TLSTEntry);
18688 else if(AVE.
Command ==
"Frh-sh")
18690 if(y == NumTrains - 1)
18696 LocServiceTimesVector.push_back(TLSTEntry);
18702 LocServiceTimesVector.push_back(TLSTEntry);
18715 SequenceLog +=
"5\n";
18748 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18751 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18752 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18754 std::ofstream TTFile3(TTFileName3.c_str());
18758 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18762 if(LocServiceTimesVector.empty())
18764 ShowMessage(
"No timetabled services found");
18766 DeleteFile(TTFileName3);
18770 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18771 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18772 SequenceLog +=
"6\n";
19001 Ptr1 = LocServiceTimesVector.begin();
19003 while(Ptr2 != LocServiceTimesVector.end())
19005 while(Ptr2->Location == Ptr1->Location)
19008 if(Ptr2 == LocServiceTimesVector.end())
19015 if(Ptr2 != LocServiceTimesVector.end())
19023 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19024 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19025 MinuteString =
" minutes";
19026 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19029 MinuteString =
" minute";
19031 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19032 TTFile3 <<
",Platforms,Trains\n\n";
19034 Ptr1 = LocServiceTimesVector.begin();
19036 while(Ptr2 != LocServiceTimesVector.end())
19038 PreviousService =
"";
19039 NumTrainsAtLoc = 0;
19040 ServiceAndRepeatNumTotal =
"";
19042 NumPlatsAtThisLocCalculated =
false;
19044 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19046 PreviousService =
"";
19047 NumTrainsAtLoc = 0;
19048 ServiceAndRepeatNumTotal =
"";
19050 NumPlatsAtThisLocCalculated =
false;
19054 if(Ptr2 == LocServiceTimesVector.end())
19059 if(Ptr2 == LocServiceTimesVector.end())
19063 while(Ptr2->Location == Ptr1->Location)
19065 PreviousService =
"";
19066 NumTrainsAtLoc = 0;
19067 ServiceAndRepeatNumTotal =
"";
19068 BasicTime = Ptr1->ArrTime;
19069 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19073 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19075 BasicTime = Ptr2->ArrTime;
19078 if(Ptr2 == LocServiceTimesVector.end())
19082 if(Ptr2->Location != Ptr1->Location)
19087 if(Ptr2 == LocServiceTimesVector.end())
19091 if(Ptr2->Location != Ptr1->Location)
19097 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19101 if(!NumPlatsAtThisLocCalculated)
19104 NumPlatsAtThisLocCalculated =
true;
19106 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19108 if(ServiceAndRepeatNumTotal ==
"")
19110 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19111 NumTrainsAtLoc = 1;
19115 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19118 PreviousService = Ptr2->ServiceAndRepeatNum;
19119 if(ServiceAndRepeatNumTotal ==
"")
19121 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19122 NumTrainsAtLoc = 1;
19126 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19130 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19132 int MaxNumberOfSameDirections = 0;
19133 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19138 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19142 AnsiString Asterisk =
"";
19143 if(MaxNumberOfSameDirections >= NumPlats)
19148 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19149 ArrivalsPrinted =
true;
19150 ServiceAndRepeatNumTotal =
"";
19152 if(Ptr2 == LocServiceTimesVector.end())
19156 if(Ptr2->Location != Ptr1->Location)
19161 if(Ptr2 == LocServiceTimesVector.end())
19167 if(!ArrivalsPrinted)
19169 TTFile3 <<
"Nothing to report for arrivals";
19174 SequenceLog +=
"7\n";
19179 Ptr1 = LocServiceTimesVector.begin();
19181 while(Ptr2 != LocServiceTimesVector.end())
19183 while(Ptr2->Location == Ptr1->Location)
19186 if(Ptr2 == LocServiceTimesVector.end())
19193 if(Ptr2 != LocServiceTimesVector.end())
19200 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19201 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19202 MinuteString =
" minutes";
19203 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19206 MinuteString =
" minute";
19208 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19209 TTFile3 <<
",Platforms,Trains\n\n";
19211 Ptr1 = LocServiceTimesVector.begin();
19213 while(Ptr2 != LocServiceTimesVector.end())
19215 PreviousService =
"";
19216 NumTrainsAtLoc = 0;
19217 ServiceAndRepeatNumTotal =
"";
19219 NumPlatsAtThisLocCalculated =
false;
19221 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19223 PreviousService =
"";
19224 NumTrainsAtLoc = 0;
19225 ServiceAndRepeatNumTotal =
"";
19227 NumPlatsAtThisLocCalculated =
false;
19231 if(Ptr2 == LocServiceTimesVector.end())
19236 if(Ptr2 == LocServiceTimesVector.end())
19240 while(Ptr2->Location == Ptr1->Location)
19242 PreviousService =
"";
19243 NumTrainsAtLoc = 0;
19244 ServiceAndRepeatNumTotal =
"";
19245 BasicTime = Ptr1->DepTime;
19246 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19250 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19252 BasicTime = Ptr2->DepTime;
19255 if(Ptr2 == LocServiceTimesVector.end())
19259 if(Ptr2->Location != Ptr1->Location)
19264 if(Ptr2 == LocServiceTimesVector.end())
19268 if(Ptr2->Location != Ptr1->Location)
19274 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19278 if(!NumPlatsAtThisLocCalculated)
19281 NumPlatsAtThisLocCalculated =
true;
19283 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19285 if(ServiceAndRepeatNumTotal ==
"")
19287 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19288 NumTrainsAtLoc = 1;
19292 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19295 PreviousService = Ptr2->ServiceAndRepeatNum;
19296 if(ServiceAndRepeatNumTotal ==
"")
19298 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19299 NumTrainsAtLoc = 1;
19303 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19307 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19309 int MaxNumberOfSameDirections = 0;
19310 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19315 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19319 AnsiString Asterisk =
"";
19320 if(MaxNumberOfSameDirections >= NumPlats)
19325 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19326 DeparturesPrinted =
true;
19327 ServiceAndRepeatNumTotal =
"";
19329 if(Ptr2 == LocServiceTimesVector.end())
19333 if(Ptr2->Location != Ptr1->Location)
19338 if(Ptr2 == LocServiceTimesVector.end())
19344 if(!DeparturesPrinted)
19346 TTFile3 <<
"Nothing to report for departures";
19351 SequenceLog +=
"8\n";
19358 Ptr1 = LocServiceTimesVector.begin();
19360 while(Ptr2 != LocServiceTimesVector.end())
19362 while(Ptr2->Location == Ptr1->Location)
19365 if(Ptr2 == LocServiceTimesVector.end())
19372 if(Ptr2 != LocServiceTimesVector.end())
19379 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19380 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19381 TTFile3 <<
",Platforms,Trains,\n\n";
19382 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19383 Ptr1 = LocServiceTimesVector.begin();
19385 while(Ptr2 != LocServiceTimesVector.end())
19387 PreviousService =
"";
19388 ServiceAndRepeatNumTotal =
"";
19389 NumTrainsAtLoc = 0;
19391 NumPlatsAtThisLocCalculated =
false;
19394 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19396 PreviousService =
"";
19397 ServiceAndRepeatNumTotal =
"";
19398 NumTrainsAtLoc = 0;
19400 NumPlatsAtThisLocCalculated =
false;
19404 if(Ptr2 == LocServiceTimesVector.end())
19409 if(Ptr2 == LocServiceTimesVector.end())
19413 while(Ptr2->Location == Ptr1->Location)
19415 if(Ptr1->FrhMarker ==
"Frh")
19418 Ptr1->FrhMarker =
"FrhCounted";
19420 PreviousService =
"";
19421 NumTrainsAtLoc = 0;
19422 ServiceAndRepeatNumTotal =
"";
19423 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19427 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19430 if(Ptr1->FrhMarker ==
"Frh")
19433 Ptr1->FrhMarker =
"FrhCounted";
19436 if(Ptr2 == LocServiceTimesVector.end())
19440 if(Ptr2->Location != Ptr1->Location)
19445 if(Ptr2 == LocServiceTimesVector.end())
19449 if(Ptr2->Location != Ptr1->Location)
19453 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19455 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19459 if(!NumPlatsAtThisLocCalculated)
19462 NumPlatsAtThisLocCalculated =
true;
19464 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19466 if(ServiceAndRepeatNumTotal ==
"")
19468 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19469 NumTrainsAtLoc = 1;
19473 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19476 PreviousService = Ptr2->ServiceAndRepeatNum;
19477 if(ServiceAndRepeatNumTotal ==
"")
19479 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19480 NumTrainsAtLoc = 1;
19484 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19487 if(Ptr1->FrhMarker ==
"Frh")
19490 Ptr1->FrhMarker =
"FrhCounted";
19493 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19497 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19499 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19501 AnsiString Asterisk =
"";
19502 if(NumTrainsAtLoc > NumPlats)
19509 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19511 else if(FrhCount == 1)
19513 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19517 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19519 LastFrhCount = FrhCount;
19520 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19521 AtLocsPrinted =
true;
19522 ServiceAndRepeatNumTotal =
"";
19525 if(Ptr2 == LocServiceTimesVector.end())
19529 if(Ptr2->Location != Ptr1->Location)
19534 if(Ptr2 == LocServiceTimesVector.end())
19542 TTFile3 <<
"Nothing to report for trains at locations";
19547 SequenceLog +=
"9\n";
19581 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19586 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19595 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19597 SingleServiceEntry = TDE;
19599 for(
unsigned int y = 0; y < SSAV.size(); y++)
19601 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19603 SingleServiceVector.push_back(SingleServiceEntry);
19606 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19608 PartServiceEntry = TDE;
19610 for(
unsigned int z = 0; z <= y; z++)
19615 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19616 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19619 PartServiceVector.push_back(PartServiceEntry);
19620 if(SSAV.at(y).Command ==
"fsp")
19622 SSAV.at(y).Command =
"Front split - original service continues below";
19623 SSAV.at(y).OtherHeadCode =
"";
19625 if(SSAV.at(y).Command ==
"rsp")
19627 SSAV.at(y).Command =
"Rear split - original service continues below";
19628 SSAV.at(y).OtherHeadCode =
"";
19632 else if(SSAV.at(y).Command ==
"Fns")
19634 SSAV.at(y).Command =
"chr-Fns";
19635 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19636 PartServiceVector.push_back(SingleServiceEntry);
19639 else if(SSAV.at(y).Command ==
"Fns-sh")
19641 SSAV.at(y).Command =
"chr-Fns-sh";
19642 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19643 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19644 PartServiceVector.push_back(SingleServiceEntry);
19647 else if(SSAV.at(y).Command ==
"F-nshs")
19649 SSAV.at(y).Command =
"chr-F-nshs";
19650 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19651 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19652 PartServiceVector.push_back(SingleServiceEntry);
19658 SequenceLog +=
"10\n";
19662 AnsiString NextRef;
19663 while(!PartServiceVector.empty())
19665 PartServiceEntry = PartServiceVector.at(0);
19666 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19668 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19670 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19674 bool FinishType =
true, FoundFlag =
false;
19681 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19685 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19689 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19695 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19696 SingleServiceVector.push_back(PartServiceVector.at(0));
19697 PartServiceVector.erase(PartServiceVector.begin());
19702 NewPartServiceEntry = PartServiceVector.at(0);
19706 PartServiceVector.push_back(NewPartServiceEntry);
19709 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19714 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19717 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19719 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19722 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19724 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19727 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19730 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19731 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19732 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19733 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19736 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19740 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19741 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19742 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19750 SequenceLog += +
"11\n";
19751 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19755 if(!PartServiceVector.empty())
19757 SequenceLog +=
"12\n";
19758 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19760 SequenceLog +=
"13\n";
19807 bool BufferFacingUnReportedFlag =
true;
19808 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19814 SequenceLog +=
"13a\n";
19815 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19818 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19820 bool BufferFlag =
false;
19821 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19822 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19823 AnsiString FrontLocName = AV.at(0).LocationName;
19824 int NextEntryPos, NextExitPos;
19827 if(ThisElement.
Conn[0] == RearTVPos)
19831 else if(ThisElement.
Conn[1] == RearTVPos)
19835 else if(ThisElement.
Conn[2] == RearTVPos)
19839 else if(ThisElement.
Conn[3] == RearTVPos)
19851 if(ThisElement.
Conn[ThisExitPos] == -1)
19853 SequenceLog =
"13b\n";
19854 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19857 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19858 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19860 BufferFlag =
false;
19865 BufferFlag =
false;
19870 BufferFlag =
false;
19878 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19880 ThisElement = NextElement;
19886 if(NextEntryPos == 0)
19890 else if(NextEntryPos == 1)
19894 else if(NextEntryPos == 2)
19898 else if(NextEntryPos == 3)
19903 ThisElement = NextElement;
19904 ThisExitPos = NextExitPos;
19909 if(BufferFacingUnReportedFlag)
19911 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19912 BufferFacingUnReportedFlag =
false;
19914 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
19918 if(BufferFacingUnReportedFlag)
19920 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19926 SequenceLog +=
"13c\n";
19929 AnsiString LocationNameToBeChecked =
"";
19930 bool MissingcdtUnreportedFlag =
true;
19932 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19935 unsigned int y = 0;
19936 int FirstInstance = 9999, SecondInstance = 9999;
19937 bool FullBreak =
false;
19938 MarkerList.clear();
19945 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19954 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19956 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19961 (AVEntry.
Command ==
"Frh-sh"))
19976 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
19982 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
19984 SecondInstance = a;
19986 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
19988 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
19990 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
19993 if(MissingcdtUnreportedFlag)
19995 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
19997 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
19998 MarkerList.push_back(FirstInstance);
19999 MarkerList.push_back(SecondInstance);
20001 MissingcdtUnreportedFlag =
false;
20012 if(MissingcdtUnreportedFlag)
20014 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20020 SequenceLog +=
"14\n";
20029 typedef std::list<AnsiString> TLocList;
20030 TLocList BackwardList, ForwardList;
20031 bool IntroLineNeeded =
true;
20032 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20034 unsigned int cdtPosition = 9999;
20035 AnsiString cdtLocation =
"";
20036 bool FoundSameName =
false;
20037 MarkerList.clear();
20039 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
20042 BackwardList.clear();
20043 ForwardList.clear();
20047 (AVEntry.
Command ==
"Frh-sh"))
20049 if(MarkerList.empty())
20056 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20058 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20060 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20064 if(IntroLineNeeded)
20066 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20067 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20068 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20069 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20070 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20071 IntroLineNeeded =
false;
20073 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20085 for(
int z = y - 1; z >= 0; z--)
20088 if(AVEntry2.
Command ==
"cdt")
20097 BackwardList.sort();
20098 BackwardList.unique();
20099 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20113 ForwardList.sort();
20114 ForwardList.unique();
20115 FoundSameName =
false;
20117 if(!BackwardList.empty() && !ForwardList.empty())
20119 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20121 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20125 FoundSameName =
true;
20132 MarkerList.push_back(cdtPosition);
20136 if(IntroLineNeeded)
20138 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20156 SequenceLog +=
"15\n";
20162 catch(
const Exception &e)
20164 AnsiString TTErrorFileName =
"Analysis Error.txt";
20165 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20166 std::ofstream TTError(TTErrorFileName.c_str());
20169 ShowMessage(
"Analysis error file failed to open - can't be created");
20173 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20174 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20175 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20178 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20188 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20190 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20192 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20194 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20195 AnsiString Marker =
"";
20196 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20199 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20201 if(
int(x) == *MLIt)
20231 if(AVE.
Command.SubString(1,3) ==
"chr")
20240 AVE.
Command =
"Change of service to ";
20242 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20244 AVE.
Command =
"Change to shuttle finishing service";
20246 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20273 AnsiString ListOfExits =
"";
20282 VecFile << Marker <<
"Frh" <<
'\n';
20297 for(
unsigned int x = 0; x < Vector.size(); x++)
20300 if(Vector.at(x).ServiceReference == HeadCode)
20302 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20304 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20307 FinishType =
false;
20312 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20315 FinishType =
false;
20320 return(Vector.at(x));
20324 return(Vector.at(Vector.size() - 1));
20333 if((Time1 ==
"") || (Time2 ==
""))
20338 int Mins = Time1.SubString(4,2).ToInt();
20339 int Hours = Time1.SubString(1,2).ToInt();
20340 int Time1Mins = (Hours * 60) + Mins;
20341 Mins = Time2.SubString(4,2).ToInt();
20342 Hours = Time2.SubString(1,2).ToInt();
20343 int Time2Mins = (Hours * 60) + Mins;
20344 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20356 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20363 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20365 std::list<AnsiString> ServiceList;
20367 bool EvenComma =
false;
20368 for(
int x = 1; x <= Input.Length(); x++)
20370 TempStr1 = Input[x];
20371 if(TempStr1 == AnsiString(
',') && EvenComma)
20377 TempStr2 += Input[x];
20379 if(TempStr1 == AnsiString(
','))
20381 EvenComma = !EvenComma;
20385 while(TempStr2.Length() > 0)
20387 SCPos = TempStr2.Pos(
';');
20390 OneService = TempStr2.SubString(1, SCPos - 1);
20391 ServiceList.push_back(OneService);
20392 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20396 ServiceList.push_back(TempStr2);
20400 ServiceList.sort();
20401 ServiceList.unique();
20402 NumTrainsAtLoc = ServiceList.size();
20405 int DirectionMarker = 0;
20407 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20409 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20411 *SLIt = *SLIt +
"&0";
20413 SLIt3 = ServiceList.end();
20415 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20416 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20417 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20419 MaxNumberOfSameDirections = 0;
20420 int SameDirectionCount = 0;
20422 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20426 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20432 CommaPos1 = SLIt1->Pos(
',');
20433 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20435 SpacePos = ServiceRef1.Pos(
' ');
20439 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20440 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20441 if(RepeatInfo1[1] ==
'F')
20447 SpacePos = RepeatInfo1.Pos(
' ');
20448 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20451 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20453 AmpersandPos = AnsiTime1.Pos(
'&');
20454 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20459 throw Exception(
"ASCLIt1 Error in " + Input);
20461 ServiceCallingLocsList1 = ASCLIt1->second;
20462 AmpersandPos = SLIt1->Pos(
'&');
20463 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20464 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20466 SameDirectionCount = 1;
20467 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20469 CommaPos2 = SLIt2->Pos(
',');
20470 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20472 SpacePos = ServiceRef2.Pos(
' ');
20476 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20477 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20478 if(RepeatInfo2[1] ==
'F')
20484 SpacePos = RepeatInfo2.Pos(
' ');
20485 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20488 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20490 AmpersandPos = AnsiTime2.Pos(
'&');
20491 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20496 throw Exception(
"ASCLIt2 Error in " + Input);
20498 ServiceCallingLocsList2 = ASCLIt2->second;
20500 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20502 int AmpersandPos = SLIt2->Pos(
'&');
20503 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20504 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20505 SameDirectionCount++;
20508 if(SameDirectionCount > MaxNumberOfSameDirections)
20510 MaxNumberOfSameDirections = SameDirectionCount;
20515 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20518 AmpersandPos = SLIt3->Pos(
'&');
20519 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20520 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20523 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20526 AmpersandPos = SLIt->Pos(
'&');
20527 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20528 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20529 DirectionMarker = DirectionMarkerString.ToInt();
20530 AnsiString DirectionSuffix =
"";
20532 if(DirectionMarker < 27)
20534 c = 64 + DirectionMarker;
20535 DirectionSuffix =
"," + AnsiString(c);
20537 else if(DirectionMarker < 53)
20539 c = 65 + DirectionMarker - 27;
20540 DirectionSuffix =
",A" + AnsiString(c);
20544 DirectionSuffix =
",?";
20546 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20549 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20551 Output = Output + *SLIt +
",";
20553 if(Output.Length() > 0)
20555 Output = Output.SubString(1, Output.Length() - 1);
20561 catch(
const Exception &e)
20563 AnalysisError =
true;
20575 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20577 std::list<AnsiString> ServiceList;
20579 while(InternalInput.Length() > 0)
20581 CommaPos = InternalInput.Pos(
',');
20584 OneService = InternalInput.SubString(1, CommaPos - 1);
20585 ServiceList.push_back(OneService);
20586 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20590 ServiceList.push_back(InternalInput);
20591 InternalInput =
"";
20595 ServiceList.sort();
20596 ServiceList.unique();
20597 NumTrainsAtLoc = ServiceList.size();
20598 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20600 Output = Output + *SLIt +
",";
20602 if(Output.Length() > 0)
20604 Output = Output.SubString(1, Output.Length() - 1);
20617 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20619 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20624 bool LocFound =
false;
20625 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20627 TDateTime FirstServiceTime;
20630 int Ref1Target = 0, Ref1Count = 0;
20631 int Ref2Target = 0, Ref2Count = 0;
20649 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20652 if((*ListPtr1) == Location)
20654 LocPtr1 = ListPtr1;
20657 if(ListPtr1->SubString(1, 3) ==
"%%%")
20659 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20664 FirstServiceTime = TDateTime(-1);
20665 bool BreakFlag =
false;
20668 if(TDVIt->ServiceReference == Ref1)
20670 if(Ref1Target > Ref1Count)
20675 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20676 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20680 FirstServiceTime = AVIt->EventTime;
20686 FirstServiceTime = AVIt->ArrivalTime;
20692 FirstServiceTime = AVIt->DepartureTime;
20703 if(IncMinutes == -1)
20705 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20707 if(FirstServiceTime == TDateTime(-1))
20709 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20713 if(!Arrival && (Time1 == CDTTime))
20718 if(Arrival && (Time1 == CDTTime))
20722 if(Time1 > CDTTime)
20727 if(Time1 < CDTTime)
20740 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20742 if((*ListPtr2) == Location)
20744 LocPtr2 = ListPtr2;
20747 if(ListPtr2->SubString(1, 3) ==
"%%%")
20749 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20754 FirstServiceTime = TDateTime(-1);
20755 bool BreakFlag =
false;
20758 if(TDVIt->ServiceReference == Ref2)
20760 if(Ref2Target > Ref2Count)
20765 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20766 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20770 FirstServiceTime = AVIt->EventTime;
20776 FirstServiceTime = AVIt->ArrivalTime;
20782 FirstServiceTime = AVIt->DepartureTime;
20793 if(IncMinutes == -1)
20795 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20797 if(FirstServiceTime == TDateTime(-1))
20799 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20803 if(!Arrival && (Time2 == CDTTime))
20808 if(Arrival && (Time2 == CDTTime))
20812 if(Time2 > CDTTime)
20817 if(Time2 < CDTTime)
20832 LP1 = List1.begin();
20834 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20836 if(ListPtr1 == List1.begin())
20840 if(ListPtr1->SubString(1, 3) ==
"%%%")
20847 LP2 = List2.begin();
20849 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20851 if(ListPtr2 == List2.begin())
20855 if(ListPtr2->SubString(1, 3) ==
"%%%")
20865 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20867 if(ListPtr1 == LocPtr1)
20871 if(ListPtr1->SubString(1, 3) ==
"%%%")
20875 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20877 if(ListPtr2 == LocPtr2)
20881 if(ListPtr2->SubString(1, 3) ==
"%%%")
20885 if((*ListPtr1) == (*ListPtr2))
20902 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20904 if(ListPtr1 == List1.end())
20908 if(ListPtr1->SubString(1, 3) ==
"%%%")
20912 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20914 if(ListPtr2 == List2.end())
20918 if(ListPtr2->SubString(1, 3) ==
"%%%")
20922 if((*ListPtr1) == (*ListPtr2))
20939 if(ExitList.empty())
20945 AnsiString ExitLocList =
"";
20948 unsigned int Counter = 0;
20949 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20953 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20955 ExitLocList +=
"\n";
20958 if(StartName ==
"")
20960 if(ExitList.size() == 1)
20964 return(
" at " + ID);
20969 if(ExitList.size() < 4)
20971 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20976 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20981 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
20986 if(ExitList.size() < 4)
20988 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
20993 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
20999 if(ExitList.size() < 4)
21001 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21002 return(
" at " + StartName);
21006 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21007 return(
" at " + StartName);
21047 AnsiString FormatStr =
"####0.0";
21048 AnsiString AvLateArrMins =
"";
21049 AnsiString AvEarlyArrMins =
"";
21050 AnsiString AvLatePassMins =
"";
21051 AnsiString AvEarlyPassMins =
"";
21052 AnsiString AvLateDepMins =
"";
21053 AnsiString AvLateExitMins =
"";
21054 AnsiString AvEarlyExitMins =
"";
21057 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21090 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21091 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21103 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21107 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21115 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21119 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21127 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21135 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21139 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21143 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21147 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21151 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21155 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21160 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21164 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21168 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21172 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21176 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21180 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21184 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21188 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21193 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21197 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21201 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21205 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21209 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21211 TDateTime TempExcessLCDownTime;
21225 if(TempExcessLCDownTime > TDateTime(0))
21231 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21235 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21243 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21247 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21283 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21287 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21293 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21297 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21300 AnsiString AvLateMinsLocsNotReached =
"";
21306 if(LocsNotReached > 0)
21309 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21313 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21317 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21329 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21333 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21343 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21345 bool DerailSPADFlag =
false, CrashFlag =
false;
21347 int OverallScorePercent = 100;
21348 int TotArrDepExit = 0;
21349 double TotLateMinsFactor = 1;
21350 double MissedStopAndSPADRiskFactor = 1;
21351 double NetNegFactor = 1;
21361 OverallScorePercent = 5;
21362 DerailSPADFlag =
true;
21366 OverallScorePercent = 0;
21369 if(OverallScorePercent == 100)
21374 LatenessPenalty = 0;
21380 if(TotArrDepExit > 0)
21389 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21391 OverallScorePercent = 100 * NetNegFactor;
21394 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21397 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21398 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21399 AnsiString AddedString =
"";
21402 AddedString = OneFailureString;
21406 AddedString = TwoOrMoreFailureString;
21408 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21409 AnsiString Rating =
"";
21410 if(OverallScorePercent == 100)
21412 Rating =
"Perfect!";
21414 else if(OverallScorePercent >= 95)
21416 Rating =
"Excellent";
21418 else if(OverallScorePercent >= 90)
21420 Rating =
"Very good";
21422 else if(OverallScorePercent >= 80)
21426 else if(OverallScorePercent >= 70)
21430 else if(OverallScorePercent >= 60)
21432 Rating =
"Unacceptable" + AddedString;
21434 else if(OverallScorePercent >= 50)
21436 Rating =
"Poor" + AddedString;
21438 else if(OverallScorePercent >= 40)
21440 Rating =
"Bad" + AddedString;
21442 else if(OverallScorePercent >= 30)
21444 Rating =
"Very bad" + AddedString;
21446 else if(OverallScorePercent >= 20)
21448 Rating =
"Terrible" + AddedString;
21450 else if(OverallScorePercent >= 10)
21452 Rating =
"Appalling" + AddedString;
21454 else if(OverallScorePercent >= 5)
21458 Rating =
"Disastrous - potential loss of life";
21463 Rating =
"Dire" + AddedString;
21466 else if(OverallScorePercent < 5)
21470 Rating =
"Catastrophic - loss of life";
21474 Rating =
"Abysmal";
21477 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21481 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21483 PerfFile <<
'\n' <<
"***************************************";
21493 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21543 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21578 int IncrementalMinutes = 0;
21592 bool TrainOperatingFlag =
false;
21597 TrainOperatingFlag =
true;
21601 if(TrainOperatingFlag)
21609 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21656 AnsiString HeadCode;
21660 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21664 HCandTrainPosParam.first = HeadCode;
21665 HCandTrainPosParam.second = TrainID;
21667 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21670 OpTimeToActMultiMapEntry.first = TimeToAct;
21671 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21700 float TimeToAct = 0;
21701 int DistanceToRedSignal = 0;
21704 ContinuationEntryVecPosVector.clear();
21705 bool LaterTrain =
false;
21709 LaterTrain =
false;
21710 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21721 if(!ContinuationEntryVecPosVector.empty())
21723 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21725 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21739 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21740 AnsiString HeadCode = CTEIt->second.HeadCode;
21741 float CurrentStopTime;
21742 float LaterStopTime;
21743 float RecoverableTime;
21746 int DistanceToExit;
21748 bool SigControlAndCanPassRedSignal =
false;
21756 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21762 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21763 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21766 if(AvTrackSpeed < 30)
21770 if(DistanceToRedSignal == -1)
21776 int Speed = AvTrackSpeed;
21777 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21778 if(AvTrackSpeed > MaxSpeed)
21782 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21785 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21788 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21793 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21794 TimeToAct += MinsBefEnter;
21797 HCandTrainPosParam.first = HeadCode;
21798 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21801 if(TimeToAct < 59.9)
21803 OpTimeToActMultiMapEntry.first = TimeToAct;
21804 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21829 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21839 TimeToExitMultiMapEntry.first = ExitPair;
21840 TimeToExitMultiMapEntry.second = ExitInfo;
21850 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21851 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21860 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21861 int DistanceToRedSignal = 0;
21862 DistanceToExit = -1;
21863 ExitPair.first = -1;
21864 ExitPair.second = -1;
21865 int CumTrackSpeed = 0;
21867 int TrackSpeedCount = 0;
21868 float KmPerLocationStop;
21869 float MaxAllowableSpeed;
21879 int CurrentElement = TrackVectorPosition;
21880 int CurrentEntryPos = TrackVectorPositionEntryPos;
21885 CurrentStopTime = 0;
21887 RecoverableTime = 0;
21888 if(CurrentElement == -1)
21893 int CurrentExitPos;
21898 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21902 CurrentExitPos = 1;
21906 CurrentExitPos = 3;
21911 CurrentExitPos = 0;
21948 CurrentStopTime = float(TimeToDepart);
21954 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
21965 else if(SigControlAndCanPassRedSignal)
21970 if((NextEntryPos == 0) || (NextEntryPos == 2))
21991 CurrentElement = NextElement;
21992 CurrentEntryPos = NextEntryPos;
21993 CurrentExitPos = NextExitPos;
22005 int LaterStopNumber = 0;
22009 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22018 if(CurrentEntryPos > 1)
22033 DistanceToExit = DistanceToRedSignal;
22038 if(TrackSpeedCount > 0)
22040 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22044 if(CurrentEntryPos > 1)
22055 if(LaterStopNumber > 0)
22057 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22058 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22064 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22068 if(AvTrackSpeed > MaxAllowableSpeed)
22070 AvTrackSpeed = MaxAllowableSpeed;
22082 bool StopRequired =
false;
22099 int TrainOnElement;
22106 if(CurrentEntryPos > 1)
22115 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22124 double StopTimeDouble;
22137 if(StopTimeDouble < 0.5)
22139 StopTimeDouble = 0.5;
22143 LaterStopTime += float(StopTimeDouble);
22144 RecoverableTime += StopTimeDouble - 0.5;
22145 if((LaterStopNumber == 1) && (TrainID > -1))
22153 if((AVPtr + 1)->FormatType ==
TimeLoc)
22157 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22159 if(StopTimeDouble < 0.5)
22161 StopTimeDouble = 0.5;
22164 LaterStopTime += float(StopTimeDouble);
22165 RecoverableTime += StopTimeDouble - 0.5;
22166 if((LaterStopNumber == 1) && (TrainID > -1))
22182 if(NextElement == -1)
22191 if((NextEntryPos == 0) || (NextEntryPos == 2))
22212 CurrentElement = NextElement;
22213 CurrentEntryPos = NextEntryPos;
22214 CurrentExitPos = NextExitPos;
22219 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22232 if(TrackSpeedCount > 0)
22234 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22238 if(CurrentEntryPos > 1)
22249 if(LaterStopNumber > 0)
22251 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22252 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22258 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22262 if(AvTrackSpeed > MaxAllowableSpeed)
22264 AvTrackSpeed = MaxAllowableSpeed;
22267 return(DistanceToRedSignal);